@@ -20,11 +20,12 @@ import { Logging } from "../logging/logging.service";
2020import PouchDB from "pouchdb-browser" ;
2121import memory from "pouchdb-adapter-memory" ;
2222import { PerformanceAnalysisLogging } from "../../utils/performance-analysis-logging" ;
23- import { Injectable } from "@angular/core" ;
23+ import { Injectable , Optional } from "@angular/core" ;
2424import { firstValueFrom , Observable , Subject } from "rxjs" ;
2525import { filter } from "rxjs/operators" ;
2626import { HttpStatusCode } from "@angular/common/http" ;
2727import { environment } from "../../../environments/environment" ;
28+ import { KeycloakAuthService } from "../session/auth/keycloak/keycloak-auth.service" ;
2829
2930/**
3031 * Wrapper for a PouchDB instance to decouple the code from
@@ -66,7 +67,7 @@ export class PouchDatabase extends Database {
6667 /**
6768 * Create a PouchDB database manager.
6869 */
69- constructor ( ) {
70+ constructor ( @ Optional ( ) private authService ?: KeycloakAuthService ) {
7071 super ( ) ;
7172 }
7273
@@ -105,27 +106,55 @@ export class PouchDatabase extends Database {
105106 */
106107 initRemoteDB (
107108 dbName = `${ environment . DB_PROXY_PREFIX } /${ environment . DB_NAME } ` ,
108- fetch = this . defaultFetch ,
109109 ) : PouchDatabase {
110110 const options = {
111111 adapter : "http" ,
112112 skip_setup : true ,
113- fetch,
113+ fetch : ( url : string | Request , opts : RequestInit ) =>
114+ this . defaultFetch ( url , opts ) ,
114115 } ;
115116 this . pouchDB = new PouchDB ( dbName , options ) ;
116117 this . databaseInitialized . complete ( ) ;
117118 return this ;
118119 }
119120
120- private defaultFetch ( url , opts : any ) {
121+ private defaultFetch : Fetch = async ( url : string | Request , opts : any ) => {
121122 if ( typeof url !== "string" ) {
122- return ;
123+ const err = new Error ( "PouchDatabase.fetch: url is not a string" ) ;
124+ err [ "details" ] = url ;
125+ throw err ;
123126 }
124127
125128 const remoteUrl =
126129 environment . DB_PROXY_PREFIX + url . split ( environment . DB_PROXY_PREFIX ) [ 1 ] ;
127- return PouchDB . fetch ( remoteUrl , opts ) ;
128- }
130+ this . authService . addAuthHeader ( opts . headers ) ;
131+
132+ let result : Response ;
133+ try {
134+ result = await PouchDB . fetch ( remoteUrl , opts ) ;
135+ } catch ( err ) {
136+ Logging . warn ( "Failed to fetch from DB" , err ) ;
137+ }
138+
139+ // retry login if request failed with unauthorized
140+ if ( ! result || result . status === HttpStatusCode . Unauthorized ) {
141+ try {
142+ await this . authService . login ( ) ;
143+ this . authService . addAuthHeader ( opts . headers ) ;
144+ result = await PouchDB . fetch ( remoteUrl , opts ) ;
145+ } catch ( err ) {
146+ Logging . warn ( "Failed to fetch from DB" , err ) ;
147+ }
148+ }
149+
150+ if ( ! result || result . status >= 500 ) {
151+ throw new DatabaseException ( {
152+ error : "Failed to fetch from DB" ,
153+ actualResponse : result ,
154+ } ) ;
155+ }
156+ return result ;
157+ } ;
129158
130159 async getPouchDBOnceReady ( ) : Promise < PouchDB . Database > {
131160 await firstValueFrom ( this . databaseInitialized , {
@@ -438,7 +467,10 @@ export class PouchDatabase extends Database {
438467 * This overwrites PouchDB's error class which only logs limited information
439468 */
440469class DatabaseException extends Error {
441- constructor ( error : PouchDB . Core . Error , entityId ?: string ) {
470+ constructor (
471+ error : PouchDB . Core . Error | { [ key : string ] : any } ,
472+ entityId ?: string ,
473+ ) {
442474 super ( ) ;
443475
444476 if ( entityId ) {
0 commit comments