Skip to content

Commit 4c0d1c3

Browse files
committed
fix(assetlibrary): change connection life cycle between Lambda and Neptune
1 parent 556bfd2 commit 4c0d1c3

File tree

13 files changed

+1071
-1259
lines changed

13 files changed

+1071
-1259
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@awssolutions/cdf-assetlibrary",
5+
"comment": "Change connection life cycle between Lambda and Neptune",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@awssolutions/cdf-assetlibrary"
10+
}

source/packages/services/assetlibrary/src/@types/gremlin/index.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,10 @@ declare module 'gremlin' {
414414
export class RemoteStrategy extends process.TraversalStrategy {}
415415

416416
export class DriverRemoteConnection extends RemoteConnection {
417+
open(): Promise<void>;
417418
close(): Promise<void>;
419+
addListener(event: string | symbol, handler: (...args: any[]) => void): void;
420+
removeListener(event: string | symbol, handler: (...args: any[]) => void): void;
418421
}
419422
}
420423
}

source/packages/services/assetlibrary/src/authz/authz.full.dao.ts

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -48,44 +48,39 @@ export class AuthzDaoFull extends BaseDaoFull {
4848
const ids: string[] = deviceIds.map((d) => `device___${d}`);
4949
ids.push(...groupPaths.map((g) => `group___${g}`));
5050

51-
let results;
52-
const conn = super.getConnection();
53-
try {
54-
const traverser = conn.traversal
55-
.V(ids)
56-
.as('entity')
57-
.union(
58-
// return an item if the entity exists
59-
__.project('entity', 'exists')
60-
.by(
61-
__.select('entity').coalesce(
62-
__.values('deviceId'),
63-
__.values('groupPath')
64-
)
51+
const conn = await super.getConnection();
52+
const traverser = conn.traversal
53+
.V(ids)
54+
.as('entity')
55+
.union(
56+
// return an item if the entity exists
57+
__.project('entity', 'exists')
58+
.by(
59+
__.select('entity').coalesce(
60+
__.values('deviceId'),
61+
__.values('groupPath')
6562
)
66-
.by(__.constant(true)),
67-
// return an item if the entity is authorized
68-
__.local(
69-
__.until(__.has('groupPath', process.P.within(hierarchies)))
70-
.repeat(
71-
__.outE().has('isAuthCheck', true).otherV().simplePath().dedup()
72-
)
73-
.as('authorizedPath')
7463
)
75-
.project('entity', 'authorizedPath')
76-
.by(
77-
__.select('entity').coalesce(
78-
__.values('deviceId'),
79-
__.values('groupPath')
80-
)
64+
.by(__.constant(true)),
65+
// return an item if the entity is authorized
66+
__.local(
67+
__.until(__.has('groupPath', process.P.within(hierarchies)))
68+
.repeat(
69+
__.outE().has('isAuthCheck', true).otherV().simplePath().dedup()
8170
)
82-
.by(__.select('authorizedPath').values('groupPath'))
83-
);
71+
.as('authorizedPath')
72+
)
73+
.project('entity', 'authorizedPath')
74+
.by(
75+
__.select('entity').coalesce(
76+
__.values('deviceId'),
77+
__.values('groupPath')
78+
)
79+
)
80+
.by(__.select('authorizedPath').values('groupPath'))
81+
);
8482

85-
results = await traverser.toList();
86-
} finally {
87-
await conn.close();
88-
}
83+
const results = await traverser.toList();
8984

9085
logger.debug(
9186
`authz.full.dao listAuthorizedHierarchies: results:${JSON.stringify(results)}`

source/packages/services/assetlibrary/src/config/.env.defaults

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ CACHE_TYPES_TTL=30
2323

2424
SUPPORTED_API_VERSIONS=application/vnd.aws-cdf-v1.0+json,application/vnd.aws-cdf-v2.0+json
2525

26-
AUTHORIZATION_ENABLED=true
26+
AUTHORIZATION_ENABLED=false
2727

2828
LOGGING_LEVEL=info
2929

source/packages/services/assetlibrary/src/data/base.full.dao.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,40 @@ import { TYPES } from '../di/types';
1818
@injectable()
1919
export class BaseDaoFull {
2020
private _graph: structure.Graph;
21+
private _conn: driver.DriverRemoteConnection | null;
2122

2223
public constructor(
2324
@inject('neptuneUrl') private neptuneUrl: string,
2425
@inject(TYPES.GraphSourceFactory) graphSourceFactory: () => structure.Graph
2526
) {
2627
this._graph = graphSourceFactory();
28+
this._conn = null;
2729
}
2830

29-
protected getConnection(): NeptuneConnection {
31+
protected async getConnection(): Promise<NeptuneConnection> {
3032
logger.debug(`base.full.dao getConnection: in:`);
31-
const conn = new driver.DriverRemoteConnection(this.neptuneUrl, {
32-
mimeType: 'application/vnd.gremlin-v2.0+json',
33-
pingEnabled: false,
34-
});
33+
34+
if (this._conn == null) {
35+
logger.debug(`base.full.dao getConnection: create new connection:`);
36+
this._conn = new driver.DriverRemoteConnection(this.neptuneUrl, {
37+
mimeType: 'application/vnd.gremlin-v2.0+json',
38+
pingEnabled: false,
39+
connectOnStartup: false,
40+
});
41+
this._conn.addListener('close', (code: number, message: string) => {
42+
logger.info(`base.full.dao connection close: code: ${code}, message: ${message}`);
43+
this._conn = null;
44+
if (code === 1006) {
45+
throw new Error('Connection closed prematurely');
46+
}
47+
});
48+
await this._conn.open();
49+
}
3550

3651
logger.debug(`base.full.dao getConnection: withRemote:`);
37-
const res = new NeptuneConnection(this._graph.traversal().withRemote(conn), conn);
52+
const res = new NeptuneConnection(
53+
this._graph.traversal().withRemote(this._conn),
54+
);
3855

3956
logger.debug(`base.full.dao getConnection: exit:`);
4057
return res;
@@ -44,14 +61,9 @@ export class BaseDaoFull {
4461
export class NeptuneConnection {
4562
constructor(
4663
private _traversal: process.GraphTraversalSource,
47-
private _connection: driver.DriverRemoteConnection
4864
) {}
4965

5066
public get traversal(): process.GraphTraversalSource {
5167
return this._traversal;
5268
}
53-
54-
public async close(): Promise<void> {
55-
await this._connection.close();
56-
}
5769
}

source/packages/services/assetlibrary/src/data/common.full.dao.ts

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -146,26 +146,21 @@ export class CommonDaoFull extends BaseDaoFull {
146146
relatedUnion.range(offsetAsInt, offsetAsInt + countAsInt);
147147

148148
// build the main part of the query, unioning the related traversers with the main entity we want to return
149-
let results;
150-
const conn = super.getConnection();
151-
try {
152-
const traverser = conn.traversal
153-
.V(entityDbId)
154-
.as('main')
155-
.union(
156-
relatedUnion,
157-
__.select('main').valueMap().with_(process.withOptions.tokens)
158-
);
159-
160-
// execute and retrieve the results
161-
logger.debug(
162-
`common.full.dao listRelated: traverser: ${JSON.stringify(traverser.toString())}`
149+
const conn = await super.getConnection();
150+
const traverser = conn.traversal
151+
.V(entityDbId)
152+
.as('main')
153+
.union(
154+
relatedUnion,
155+
__.select('main').valueMap().with_(process.withOptions.tokens)
163156
);
164-
results = await traverser.toList();
165-
logger.debug(`common.full.dao listRelated: results: ${JSON.stringify(results)}`);
166-
} finally {
167-
await conn.close();
168-
}
157+
158+
// execute and retrieve the results
159+
logger.debug(
160+
`common.full.dao listRelated: traverser: ${JSON.stringify(traverser.toString())}`
161+
);
162+
const results = await traverser.toList();
163+
logger.debug(`common.full.dao listRelated: results: ${JSON.stringify(results)}`);
169164

170165
if (results === undefined || results.length === 0) {
171166
logger.debug(`common.full.dao listRelated: exit: node: undefined`);
@@ -193,20 +188,15 @@ export class CommonDaoFull extends BaseDaoFull {
193188
return {};
194189
}
195190

196-
let results;
197-
const conn = super.getConnection();
198-
try {
199-
const query = conn.traversal
200-
.V(entityDbIds)
201-
.project('id', 'labels')
202-
.by(__.coalesce(__.values('deviceId'), __.values('groupPath')))
203-
.by(__.label().fold());
204-
205-
logger.silly(`common.full.dao getLabels: query: ${JSON.stringify(query)}`);
206-
results = await query.toList();
207-
} finally {
208-
await conn.close();
209-
}
191+
const conn = await super.getConnection();
192+
const query = conn.traversal
193+
.V(entityDbIds)
194+
.project('id', 'labels')
195+
.by(__.coalesce(__.values('deviceId'), __.values('groupPath')))
196+
.by(__.label().fold());
197+
198+
logger.silly(`common.full.dao getLabels: query: ${JSON.stringify(query)}`);
199+
const results = await query.toList();
210200
logger.silly(`common.full.dao getLabels: results: ${JSON.stringify(results)}`);
211201

212202
if ((results?.length ?? 0) === 0) {

0 commit comments

Comments
 (0)