1
- import { BehaviorSubject , Observable , Subscription , filter , firstValueFrom } from 'rxjs' ;
1
+ import { BehaviorSubject , Observable , Subscription , filter , firstValueFrom , timeout } from 'rxjs' ;
2
2
import { DataSource , QueryRunner } from 'typeorm' ;
3
3
import { Logger } from 'ts-log' ;
4
+ import { Milliseconds } from '@cardano-sdk/core' ;
4
5
import { PgConnectionConfig } from '@cardano-sdk/projection-typeorm' ;
5
6
import { RunnableModule , isNotNil } from '@cardano-sdk/util' ;
6
7
import { createTypeormDataSource } from '../createTypeormDataSource' ;
7
8
8
- interface TypeormServiceDependencies {
9
+ export interface TypeormServiceDependencies {
9
10
logger : Logger ;
10
11
entities : Function [ ] ;
11
12
connectionConfig$ : Observable < PgConnectionConfig > ;
13
+ connectionTimeout : Milliseconds ;
12
14
}
13
15
14
16
export abstract class TypeormService extends RunnableModule {
15
17
#entities: Function [ ] ;
16
18
#connectionConfig$: Observable < PgConnectionConfig > ;
17
19
protected dataSource$ = new BehaviorSubject < DataSource | null > ( null ) ;
18
20
#subscription: Subscription | undefined ;
21
+ #connectionTimeout: Milliseconds ;
19
22
20
- constructor ( name : string , { connectionConfig$, logger, entities } : TypeormServiceDependencies ) {
23
+ constructor ( name : string , { connectionConfig$, logger, entities, connectionTimeout } : TypeormServiceDependencies ) {
21
24
super ( name , logger ) ;
22
25
this . #entities = entities ;
23
26
this . #connectionConfig$ = connectionConfig$ ;
27
+ this . #connectionTimeout = connectionTimeout ;
24
28
}
25
29
26
- #subscribeToDataSource( ) {
27
- this . #subscription = createTypeormDataSource ( this . #connectionConfig$, this . #entities, this . logger ) . subscribe (
28
- ( dataSource ) => this . dataSource$ . next ( dataSource )
29
- ) ;
30
+ async #subscribeToDataSource( ) {
31
+ return new Promise ( ( resolve , reject ) => {
32
+ this . #subscription = createTypeormDataSource ( this . #connectionConfig$, this . #entities, this . logger ) . subscribe (
33
+ ( dataSource ) => {
34
+ if ( dataSource !== this . dataSource$ . value ) {
35
+ this . dataSource$ . next ( dataSource ) ;
36
+ }
37
+ if ( dataSource ) {
38
+ resolve ( dataSource ) ;
39
+ } else {
40
+ reject ( new Error ( 'Failed to initialize data source' ) ) ;
41
+ }
42
+ }
43
+ ) ;
44
+ } ) ;
30
45
}
31
46
32
47
#reset( ) {
@@ -37,12 +52,16 @@ export abstract class TypeormService extends RunnableModule {
37
52
38
53
onError ( _ : unknown ) {
39
54
this . #reset( ) ;
40
- this . #subscribeToDataSource( ) ;
55
+ void this . #subscribeToDataSource( ) . catch ( ( ) => void 0 ) ;
41
56
}
42
57
43
58
async withDataSource < T > ( callback : ( dataSource : DataSource ) => Promise < T > ) : Promise < T > {
59
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
60
+ this . #connectionTimeout;
44
61
try {
45
- return await callback ( await firstValueFrom ( this . dataSource$ . pipe ( filter ( isNotNil ) ) ) ) ;
62
+ return await callback (
63
+ await firstValueFrom ( this . dataSource$ . pipe ( filter ( isNotNil ) , timeout ( { first : this . #connectionTimeout } ) ) )
64
+ ) ;
46
65
} catch ( error ) {
47
66
this . onError ( error ) ;
48
67
throw error ;
@@ -72,7 +91,7 @@ export abstract class TypeormService extends RunnableModule {
72
91
}
73
92
74
93
async startImpl ( ) {
75
- this . #subscribeToDataSource( ) ;
94
+ await this . #subscribeToDataSource( ) ;
76
95
}
77
96
78
97
async shutdownImpl ( ) {
0 commit comments