@nsshunt/stsappframework 3.1.135 → 3.1.137
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fhir/STSFhirTypes.js +3 -0
- package/dist/fhir/STSFhirTypes.js.map +1 -0
- package/dist/fhir/dalFhirManagerPGRes.js +87 -0
- package/dist/fhir/dalFhirManagerPGRes.js.map +1 -0
- package/dist/fhir/dalFhirManagerPGRes.test.js +31 -0
- package/dist/fhir/dalFhirManagerPGRes.test.js.map +1 -0
- package/dist/fhir/dalFhirManagerPGResEntity.js +116 -0
- package/dist/fhir/dalFhirManagerPGResEntity.js.map +1 -0
- package/dist/fhir/dalFhirManagerPGResEntity.test.js +32 -0
- package/dist/fhir/dalFhirManagerPGResEntity.test.js.map +1 -0
- package/dist/fhir/dalFhirManagerRedisJson.js +87 -0
- package/dist/fhir/dalFhirManagerRedisJson.js.map +1 -0
- package/dist/fhir/dalFhirManagerRedisJson.test.js +33 -0
- package/dist/fhir/dalFhirManagerRedisJson.test.js.map +1 -0
- package/dist/fhir/dalFhirTestHelpers.js +130 -0
- package/dist/fhir/dalFhirTestHelpers.js.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/masterprocessbase.js +43 -0
- package/dist/masterprocessbase.js.map +1 -1
- package/dist/redisMessageHandler.js +23 -0
- package/dist/redisMessageHandler.js.map +1 -1
- package/dist/testing/app.js +18 -3
- package/dist/testing/app.js.map +1 -1
- package/dist/workerprocessbase.js +1 -0
- package/dist/workerprocessbase.js.map +1 -1
- package/package.json +1 -1
- package/src/fhir/STSFhirTypes.ts +501 -0
- package/src/fhir/dalFhirManagerPGRes.test.ts +42 -0
- package/src/fhir/dalFhirManagerPGRes.ts +92 -0
- package/src/fhir/dalFhirManagerPGResEntity.test.ts +43 -0
- package/src/fhir/dalFhirManagerPGResEntity.ts +123 -0
- package/src/fhir/dalFhirManagerRedisJson.test.ts +44 -0
- package/src/fhir/dalFhirManagerRedisJson.ts +92 -0
- package/src/fhir/dalFhirTestHelpers.ts +163 -0
- package/src/index.ts +2 -0
- package/src/masterprocessbase.ts +53 -0
- package/src/redisMessageHandler.ts +23 -0
- package/src/testing/app.ts +21 -3
- package/src/workerprocessbase.ts +2 -0
- package/types/fhir/STSFhirTypes.d.ts +318 -0
- package/types/fhir/STSFhirTypes.d.ts.map +1 -0
- package/types/fhir/dalFhirManagerPGRes.d.ts +16 -0
- package/types/fhir/dalFhirManagerPGRes.d.ts.map +1 -0
- package/types/fhir/dalFhirManagerPGRes.test.d.ts +2 -0
- package/types/fhir/dalFhirManagerPGRes.test.d.ts.map +1 -0
- package/types/fhir/dalFhirManagerPGResEntity.d.ts +15 -0
- package/types/fhir/dalFhirManagerPGResEntity.d.ts.map +1 -0
- package/types/fhir/dalFhirManagerPGResEntity.test.d.ts +2 -0
- package/types/fhir/dalFhirManagerPGResEntity.test.d.ts.map +1 -0
- package/types/fhir/dalFhirManagerRedisJson.d.ts +17 -0
- package/types/fhir/dalFhirManagerRedisJson.d.ts.map +1 -0
- package/types/fhir/dalFhirManagerRedisJson.test.d.ts +2 -0
- package/types/fhir/dalFhirManagerRedisJson.test.d.ts.map +1 -0
- package/types/fhir/dalFhirTestHelpers.d.ts +14 -0
- package/types/fhir/dalFhirTestHelpers.d.ts.map +1 -0
- package/types/index.d.ts +2 -0
- package/types/index.d.ts.map +1 -1
- package/types/masterprocessbase.d.ts.map +1 -1
- package/types/redisMessageHandler.d.ts +1 -0
- package/types/redisMessageHandler.d.ts.map +1 -1
- package/types/workerprocessbase.d.ts.map +1 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { DBAccessLayerManager, IDBAccessLayer, IDBAccessLayerManagerOptions, IDBResource, IDBEntity } from '@nsshunt/stsdatamanagement'
|
|
2
|
+
|
|
3
|
+
import { IDomainResource, IFHIRResource, IDALFhirDataAccessManager } from './STSFhirTypes'
|
|
4
|
+
|
|
5
|
+
export interface IFhirManagerPGResEntityOptions extends IDBAccessLayerManagerOptions {
|
|
6
|
+
resourceName: string
|
|
7
|
+
dbactionuser: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class DALFhirManagerPGResEntity<T> implements IDALFhirDataAccessManager<T> {
|
|
11
|
+
#options: IFhirManagerPGResEntityOptions;
|
|
12
|
+
#accessLayer: IDBAccessLayer;
|
|
13
|
+
#fhirResource: IDBResource<IFHIRResource> | undefined;
|
|
14
|
+
|
|
15
|
+
constructor(options: IFhirManagerPGResEntityOptions) {
|
|
16
|
+
this.#options = options;
|
|
17
|
+
this.#accessLayer = new DBAccessLayerManager().CreateAccessLayer({
|
|
18
|
+
accessLayerType: options.accessLayerType,
|
|
19
|
+
accessLayerOptions: options.accessLayerOptions
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
#GetSTSFhirBaseResource = async (): Promise<IDBResource<IFHIRResource>> => {
|
|
24
|
+
if (!this.#fhirResource) {
|
|
25
|
+
this.#fhirResource = ((await this.#accessLayer.GetResource<IFHIRResource>({
|
|
26
|
+
filters: {
|
|
27
|
+
resname: this.#options.resourceName
|
|
28
|
+
}
|
|
29
|
+
})).detail as IDBResource<IFHIRResource>);
|
|
30
|
+
|
|
31
|
+
if (!this.#fhirResource) {
|
|
32
|
+
const fhirResourceType: IFHIRResource = {
|
|
33
|
+
name: this.#options.resourceName,
|
|
34
|
+
description: `${this.#options.resourceName} description`,
|
|
35
|
+
notes: `${this.#options.resourceName} notes`,
|
|
36
|
+
}
|
|
37
|
+
this.#fhirResource = ((await this.#accessLayer.CreateResource<IFHIRResource>({
|
|
38
|
+
filters: {
|
|
39
|
+
dbactionuser: this.#options.dbactionuser,
|
|
40
|
+
resname: this.#options.resourceName
|
|
41
|
+
}
|
|
42
|
+
}, fhirResourceType)).detail as IDBResource<IFHIRResource>);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return this.#fhirResource;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async GetFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
|
|
50
|
+
const fhirResource = await this.#GetSTSFhirBaseResource();
|
|
51
|
+
const retVal = await this.#accessLayer.GetEntity<T>({
|
|
52
|
+
filters: {
|
|
53
|
+
resname: fhirResource.resname,
|
|
54
|
+
entname: (fhir as Partial<IDomainResource>).id
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
if (retVal.error) {
|
|
58
|
+
if (ecb) {
|
|
59
|
+
ecb(retVal.error.error);
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
} else {
|
|
63
|
+
return (retVal.detail as IDBEntity<T>).entvalue;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
async CreateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
|
|
68
|
+
const fhirResource = await this.#GetSTSFhirBaseResource();
|
|
69
|
+
const retVal = await this.#accessLayer.CreateEntity<T>({
|
|
70
|
+
filters: {
|
|
71
|
+
dbactionuser: this.#options.dbactionuser,
|
|
72
|
+
resname: fhirResource.resname,
|
|
73
|
+
entname: (fhir as Partial<IDomainResource>).id
|
|
74
|
+
}
|
|
75
|
+
}, fhir);
|
|
76
|
+
if (retVal.error) {
|
|
77
|
+
if (ecb) {
|
|
78
|
+
ecb(retVal.error.error);
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
} else {
|
|
82
|
+
return (retVal.detail as IDBEntity<T>).entvalue;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async UpdateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
|
|
87
|
+
const fhirResource = await this.#GetSTSFhirBaseResource();
|
|
88
|
+
const retVal = await this.#accessLayer.UpdateEntity<T>({
|
|
89
|
+
filters: {
|
|
90
|
+
dbactionuser: this.#options.dbactionuser,
|
|
91
|
+
resname: fhirResource.resname,
|
|
92
|
+
entname: (fhir as Partial<IDomainResource>).id
|
|
93
|
+
}
|
|
94
|
+
}, fhir);
|
|
95
|
+
if (retVal.error) {
|
|
96
|
+
if (ecb) {
|
|
97
|
+
ecb(retVal.error.error);
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
} else {
|
|
101
|
+
return (retVal.detail as IDBEntity<T>).entvalue;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
async DeleteFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
|
|
106
|
+
const fhirResource = await this.#GetSTSFhirBaseResource();
|
|
107
|
+
const retVal = await this.#accessLayer.DeleteEntity<T>({
|
|
108
|
+
filters: {
|
|
109
|
+
dbactionuser: this.#options.dbactionuser,
|
|
110
|
+
resname: fhirResource.resname,
|
|
111
|
+
entname: (fhir as Partial<IDomainResource>).id
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
if (retVal.error) {
|
|
115
|
+
if (ecb) {
|
|
116
|
+
ecb(retVal.error.error);
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
} else {
|
|
120
|
+
return (retVal.detail as IDBEntity<T>).entvalue;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/* eslint @typescript-eslint/no-explicit-any: 0 */ // --> OFF
|
|
2
|
+
import { beforeAll, afterAll, test, describe, expect } from 'vitest';
|
|
3
|
+
|
|
4
|
+
import { DALFhirManagerRedisJson } from './dalFhirManagerRedisJson'
|
|
5
|
+
|
|
6
|
+
import { IPerson } from './STSFhirTypes'
|
|
7
|
+
|
|
8
|
+
import { TestHelpers } from './dalFhirTestHelpers'
|
|
9
|
+
|
|
10
|
+
import { JestSleep } from '@nsshunt/stsutils'
|
|
11
|
+
|
|
12
|
+
describe.skip("Test hl7 fhir resource data access layer - RedisJson", () =>
|
|
13
|
+
{
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
let personManager: DALFhirManagerRedisJson<IPerson>;
|
|
16
|
+
let testHelpers: TestHelpers;
|
|
17
|
+
|
|
18
|
+
beforeAll(async () =>
|
|
19
|
+
{
|
|
20
|
+
testHelpers = new TestHelpers();
|
|
21
|
+
await testHelpers.StartRedis();
|
|
22
|
+
|
|
23
|
+
personManager = new DALFhirManagerRedisJson<IPerson>({
|
|
24
|
+
//const personManager = new DALFhirManagerPGRes<IPerson>({
|
|
25
|
+
//const personManager = new DALFhirManagerPGResEntity<IPerson>({
|
|
26
|
+
resourceName: 'STSFhirPerson',
|
|
27
|
+
redisUrl: testHelpers.ioRedisMessageProcessorUrl
|
|
28
|
+
});
|
|
29
|
+
personManager.Start();
|
|
30
|
+
}, 30000);
|
|
31
|
+
|
|
32
|
+
test('Testing Person', async () => {
|
|
33
|
+
expect.assertions(6);
|
|
34
|
+
|
|
35
|
+
await testHelpers.TestFhirPerson(personManager);
|
|
36
|
+
}, 30000);
|
|
37
|
+
|
|
38
|
+
afterAll(async () =>
|
|
39
|
+
{
|
|
40
|
+
personManager.Stop();
|
|
41
|
+
await JestSleep();
|
|
42
|
+
await testHelpers.StopRedis();
|
|
43
|
+
}, 5000);
|
|
44
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { IDomainResource, IDALFhirDataAccessManager } from './STSFhirTypes'
|
|
2
|
+
|
|
3
|
+
import { Redis, RedisOptions } from "ioredis";
|
|
4
|
+
|
|
5
|
+
export interface IFhirManagerRedisJsonOptions {
|
|
6
|
+
redisUrl: string
|
|
7
|
+
resourceName: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export class DALFhirManagerRedisJson<T> implements IDALFhirDataAccessManager<T> {
|
|
11
|
+
#options: IFhirManagerRedisJsonOptions;
|
|
12
|
+
#redisSubscriber: Redis | null = null;
|
|
13
|
+
|
|
14
|
+
constructor(options: IFhirManagerRedisJsonOptions) {
|
|
15
|
+
this.#options = options;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
Start() {
|
|
19
|
+
const redisOptions: RedisOptions = {
|
|
20
|
+
showFriendlyErrorStack: true,
|
|
21
|
+
maxRetriesPerRequest: 20
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
this.#redisSubscriber = new Redis(this.#options.redisUrl, redisOptions);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
Stop() {
|
|
28
|
+
if (this.#redisSubscriber) {
|
|
29
|
+
this.#redisSubscriber.quit();
|
|
30
|
+
this.#redisSubscriber.disconnect();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
GetResourceType(fhir: Partial<T>): string {
|
|
35
|
+
return `${this.#options.resourceName}_${(fhir as Partial<IDomainResource>).id}`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async GetFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
|
|
39
|
+
if (this.#redisSubscriber) {
|
|
40
|
+
const retValRaw = await this.#redisSubscriber?.get(this.GetResourceType(fhir))
|
|
41
|
+
if (retValRaw) {
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(retValRaw) as T;
|
|
44
|
+
} catch (error: unknown) {
|
|
45
|
+
if (ecb) {
|
|
46
|
+
ecb(error as Error);
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
59
|
+
async CreateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
|
|
60
|
+
const retVal = await this.#redisSubscriber?.set(this.GetResourceType(fhir), JSON.stringify(fhir));
|
|
61
|
+
if (retVal) {
|
|
62
|
+
return fhir;
|
|
63
|
+
} else {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
69
|
+
async UpdateFhirResource(fhir: T, ecb?: (error: Error) => void): Promise<T | null> {
|
|
70
|
+
const retVal = await this.#redisSubscriber?.set(this.GetResourceType(fhir), JSON.stringify(fhir));
|
|
71
|
+
if (retVal) {
|
|
72
|
+
return fhir;
|
|
73
|
+
} else {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
79
|
+
async DeleteFhirResource(fhir: Partial<T>, ecb?: (error: Error) => void): Promise<T | null> {
|
|
80
|
+
const deleteResource = await this.GetFhirResource(fhir);
|
|
81
|
+
if (deleteResource) {
|
|
82
|
+
const retVal = await this.#redisSubscriber?.del(this.GetResourceType(fhir));
|
|
83
|
+
if (retVal) {
|
|
84
|
+
return deleteResource;
|
|
85
|
+
} else {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import { expect } from 'vitest';
|
|
2
|
+
import { IDALFhirDataAccessManager, INarrative, IPerson } from './STSFhirTypes'
|
|
3
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
4
|
+
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
|
|
7
|
+
import { goptions, $ResetOptions } from '@nsshunt/stsconfig'
|
|
8
|
+
|
|
9
|
+
import { JestSleep, defaultLogger, Sleep } from '@nsshunt/stsutils'
|
|
10
|
+
|
|
11
|
+
import { DatabaseUtils, DBAccessLayerManager, IDBAccessLayer, accessLayerType, IPGAccessLayerOptions } from '@nsshunt/stsdatamanagement'
|
|
12
|
+
|
|
13
|
+
import { GenericContainer } from "testcontainers";
|
|
14
|
+
|
|
15
|
+
import winston from 'winston'
|
|
16
|
+
|
|
17
|
+
export class TestHelpers {
|
|
18
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
19
|
+
#postgresContainer: any;
|
|
20
|
+
#accessLayer: IDBAccessLayer | null = null;
|
|
21
|
+
#logger: winston.Logger;
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
+
#ioRedisContainer: any;
|
|
24
|
+
#ioRedisMessageProcessorUrl = '';
|
|
25
|
+
|
|
26
|
+
constructor() {
|
|
27
|
+
winston.format.combine(
|
|
28
|
+
winston.format.colorize(),
|
|
29
|
+
winston.format.simple()
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
this.#logger = winston.createLogger({
|
|
33
|
+
level: 'silly',
|
|
34
|
+
format: winston.format.combine(
|
|
35
|
+
winston.format.colorize(),
|
|
36
|
+
winston.format.simple()
|
|
37
|
+
),
|
|
38
|
+
transports: [
|
|
39
|
+
new winston.transports.Console(),
|
|
40
|
+
]});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
get logger(): winston.Logger {
|
|
44
|
+
return this.#logger;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
TestFhirPerson = async (personManager: IDALFhirDataAccessManager<IPerson>) => {
|
|
48
|
+
expect.assertions(6);
|
|
49
|
+
|
|
50
|
+
const id = uuidv4();
|
|
51
|
+
|
|
52
|
+
const personRecord: IPerson = {
|
|
53
|
+
id,
|
|
54
|
+
_resourceType: 'Person',
|
|
55
|
+
name: [
|
|
56
|
+
{
|
|
57
|
+
family: 'family',
|
|
58
|
+
given: [ 'given' ],
|
|
59
|
+
use: 'usual'
|
|
60
|
+
}
|
|
61
|
+
],
|
|
62
|
+
text: {
|
|
63
|
+
div: 'New Record',
|
|
64
|
+
status: 'generated'
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const newPerson01 = await personManager.CreateFhirResource(personRecord);
|
|
69
|
+
expect(newPerson01).toMatchObject(personRecord);
|
|
70
|
+
|
|
71
|
+
(personRecord.text as INarrative).div = 'user01 updated at ' + new Date().toString();
|
|
72
|
+
const updatedPerson01 = await personManager.UpdateFhirResource(personRecord);
|
|
73
|
+
expect(updatedPerson01).toMatchObject(personRecord);
|
|
74
|
+
|
|
75
|
+
const getPerson01 = await personManager.GetFhirResource({id})
|
|
76
|
+
expect(getPerson01).toMatchObject(personRecord);
|
|
77
|
+
|
|
78
|
+
const getPerson02 = await personManager.GetFhirResource({id:'willnotfind'})
|
|
79
|
+
expect(getPerson02).toBeNull();
|
|
80
|
+
|
|
81
|
+
const deletePerson01 = await personManager.DeleteFhirResource({id})
|
|
82
|
+
expect(deletePerson01).toMatchObject(personRecord);
|
|
83
|
+
|
|
84
|
+
const getPerson01AfterDelete = await personManager.GetFhirResource({id})
|
|
85
|
+
expect(getPerson01AfterDelete).toBeNull();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
StartDatabase = async() => {
|
|
89
|
+
this.#postgresContainer = await new GenericContainer("postgres")
|
|
90
|
+
.withExposedPorts(5432)
|
|
91
|
+
.withEnvironment({
|
|
92
|
+
POSTGRES_PASSWORD: "postgres",
|
|
93
|
+
//UV_THREADPOOL_SIZE: "64"
|
|
94
|
+
})
|
|
95
|
+
.withCommand(['-c', 'max_connections=20'])
|
|
96
|
+
.start();
|
|
97
|
+
|
|
98
|
+
await Sleep(1000);
|
|
99
|
+
|
|
100
|
+
const postgresHttpPort = this.#postgresContainer.getMappedPort(5432);
|
|
101
|
+
const postgresHost = this.#postgresContainer.getHost();
|
|
102
|
+
|
|
103
|
+
process.env.DB_HOST = `${postgresHost}:${postgresHttpPort}`;
|
|
104
|
+
process.env.POOL_SIZE = '10';
|
|
105
|
+
|
|
106
|
+
$ResetOptions();
|
|
107
|
+
|
|
108
|
+
this.logger.info(chalk.green(`httpPort: [${postgresHttpPort}]`));
|
|
109
|
+
this.logger.info(chalk.green(`host: [${postgresHost}]`));
|
|
110
|
+
this.logger.info(chalk.yellow(`connectionString: [${goptions.connectionString}]`));
|
|
111
|
+
this.logger.info(chalk.yellow(`defaultDatabaseConnectionString: [${goptions.defaultDatabaseConnectionString }]`));
|
|
112
|
+
|
|
113
|
+
const dbOptions = {
|
|
114
|
+
start: 0,
|
|
115
|
+
iterations: 10000,
|
|
116
|
+
minextradata: 0,
|
|
117
|
+
maxextradata: 1000,
|
|
118
|
+
workerScriptFolder: './dist', //@@
|
|
119
|
+
useMultiBar: false
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const dbUtils = new DatabaseUtils({
|
|
123
|
+
logger: this.logger
|
|
124
|
+
});
|
|
125
|
+
await dbUtils.CreateDatabase(dbOptions);
|
|
126
|
+
|
|
127
|
+
await Sleep(1000);
|
|
128
|
+
|
|
129
|
+
this.logger.info(chalk.green(`Starting accessLayer`));
|
|
130
|
+
|
|
131
|
+
this.#accessLayer = new DBAccessLayerManager().CreateAccessLayer({
|
|
132
|
+
accessLayerType: accessLayerType.postgresql,
|
|
133
|
+
accessLayerOptions: {
|
|
134
|
+
logger: defaultLogger,
|
|
135
|
+
usedefaultdb: false
|
|
136
|
+
} as IPGAccessLayerOptions
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
this.logger.info(chalk.green(`accessLayer:startdatabase()`));
|
|
140
|
+
await this.#accessLayer.StartDatabase();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
StopDatabase = async () => {
|
|
144
|
+
await this.#accessLayer?.EndDatabase();
|
|
145
|
+
await JestSleep();
|
|
146
|
+
await this.#postgresContainer.stop();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
StartRedis = async () => {
|
|
150
|
+
this.#ioRedisContainer = await new GenericContainer("redis")
|
|
151
|
+
.withExposedPorts(6379)
|
|
152
|
+
.start();
|
|
153
|
+
this.#ioRedisMessageProcessorUrl = `redis://${this.#ioRedisContainer.getHost()}:${this.#ioRedisContainer.getMappedPort(6379)}`;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
get ioRedisMessageProcessorUrl() {
|
|
157
|
+
return this.#ioRedisMessageProcessorUrl;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
StopRedis = async () => {
|
|
161
|
+
await this.#ioRedisContainer.stop();
|
|
162
|
+
}
|
|
163
|
+
}
|
package/src/index.ts
CHANGED
package/src/masterprocessbase.ts
CHANGED
|
@@ -32,6 +32,8 @@ import { ISTSLogger, JSONObject } from "@nsshunt/stsutils";
|
|
|
32
32
|
|
|
33
33
|
import { RedisMessageHandler } from './redisMessageHandler';
|
|
34
34
|
|
|
35
|
+
import { GetFirstNetworkInterface } from './network';
|
|
36
|
+
|
|
35
37
|
export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
36
38
|
{
|
|
37
39
|
//static WORKER_MESSAGE_EVENT = 'sts_worker_message_event';
|
|
@@ -632,6 +634,13 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
632
634
|
});
|
|
633
635
|
*/
|
|
634
636
|
|
|
637
|
+
this.redisMessageHandler.AddGroup('primary');
|
|
638
|
+
|
|
639
|
+
this.redisMessageHandler.on('GetSystemInformation', async (args: JSONObject, callback: any) => {
|
|
640
|
+
const retVal = await this.#GetSystemInformation();
|
|
641
|
+
callback(retVal);
|
|
642
|
+
});
|
|
643
|
+
|
|
635
644
|
this.MasterStarted();
|
|
636
645
|
|
|
637
646
|
this.LogInfoMessage(chalk.green(`Master process:${process.pid} started`));
|
|
@@ -651,4 +660,48 @@ export class MasterProcessBase extends ProcessBase implements IMasterProcessBase
|
|
|
651
660
|
//@@this.LogInfoMessage(error);
|
|
652
661
|
}
|
|
653
662
|
}
|
|
663
|
+
|
|
664
|
+
#GetSystemInformation = async (): Promise<JSONObject> => {
|
|
665
|
+
// https://systeminformation.io/
|
|
666
|
+
const valueObject = {
|
|
667
|
+
system: '*',
|
|
668
|
+
osInfo: '*',
|
|
669
|
+
cpu: '*',
|
|
670
|
+
mem: '*',
|
|
671
|
+
dockerInfo: '*',
|
|
672
|
+
//dockerImages: '*',
|
|
673
|
+
dockerContainers: '*',
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
const sysinfo = await si.get(valueObject);
|
|
677
|
+
const numCPUs = await this.GetNumCPUs();
|
|
678
|
+
const hostname = sysinfo.osInfo.hostname;
|
|
679
|
+
|
|
680
|
+
const hostaddr = GetFirstNetworkInterface();
|
|
681
|
+
|
|
682
|
+
const promArray: Promise<any>[] = [ ];
|
|
683
|
+
|
|
684
|
+
sysinfo.dockerContainers.forEach((dc: { id: string; }) => {
|
|
685
|
+
const dcs = promArray.push(si.dockerContainerStats(dc.id));
|
|
686
|
+
console.log(dcs);
|
|
687
|
+
});
|
|
688
|
+
const dockerContainerStats = await Promise.all(promArray);
|
|
689
|
+
|
|
690
|
+
const sysInfo = {
|
|
691
|
+
serviceProcessContext: this.options.serviceProcessContext,
|
|
692
|
+
hostname,
|
|
693
|
+
numCPUs,
|
|
694
|
+
hostaddr,
|
|
695
|
+
system: sysinfo.system,
|
|
696
|
+
osInfo: sysinfo.osInfo,
|
|
697
|
+
cpu: sysinfo.cpu,
|
|
698
|
+
mem: sysinfo.mem,
|
|
699
|
+
dockerInfo: sysinfo.dockerInfo,
|
|
700
|
+
//dockerImages: sysinfo.dockerImages,
|
|
701
|
+
dockerContainers: sysinfo.dockerContainers,
|
|
702
|
+
dockerContainerStats
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
return sysInfo;
|
|
706
|
+
}
|
|
654
707
|
}
|
|
@@ -341,6 +341,29 @@ export class RedisMessageHandler extends TinyEmitter {
|
|
|
341
341
|
return this;
|
|
342
342
|
}
|
|
343
343
|
|
|
344
|
+
emitWithError(event: string, args: JSONObject, responseCb: (response: JSONObject | undefined) => void, errorCb: (error: any) => void): this {
|
|
345
|
+
(async () => {
|
|
346
|
+
try {
|
|
347
|
+
const retVal = await this.#ipcMessageManager?.SendMessage({
|
|
348
|
+
__eventName: event,
|
|
349
|
+
args: [ args ]
|
|
350
|
+
} as IEventPayload);
|
|
351
|
+
// Invoke the response callback
|
|
352
|
+
responseCb(retVal);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
if (this.#options.ignoreEvents) {
|
|
355
|
+
//console.log(chalk.red(`RedisMessageHandler:emit(): ignoreEvents: [${this.#options.ignoreEvents}]`))
|
|
356
|
+
if (this.#options.ignoreEvents.indexOf((error as any).__eventName) !== -1) {
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
//this.#options.logger.error(chalk.red(`RedisMessageHandler:emit(): Error: [${JSON.stringify(error)}]`));
|
|
361
|
+
errorCb(error);
|
|
362
|
+
}
|
|
363
|
+
})();
|
|
364
|
+
return this;
|
|
365
|
+
}
|
|
366
|
+
|
|
344
367
|
emitex = async(event: string, ...args: any[]): Promise<JSONObject> => {
|
|
345
368
|
return (this.#ipcMessageManager as IPCMessageManager).SendMessage({
|
|
346
369
|
__eventName: event,
|
package/src/testing/app.ts
CHANGED
|
@@ -385,7 +385,7 @@ if (cluster.isPrimary) {
|
|
|
385
385
|
})();
|
|
386
386
|
}, 250);
|
|
387
387
|
}
|
|
388
|
-
setTimeout(() => xxx(), 1000);
|
|
388
|
+
//setTimeout(() => xxx(), 1000);
|
|
389
389
|
|
|
390
390
|
|
|
391
391
|
|
|
@@ -435,11 +435,12 @@ if (cluster.isPrimary) {
|
|
|
435
435
|
ListClients();
|
|
436
436
|
}, 1000).unref();
|
|
437
437
|
}
|
|
438
|
-
ListClients();
|
|
438
|
+
//ListClients();
|
|
439
439
|
|
|
440
440
|
|
|
441
441
|
} else {
|
|
442
|
-
new WorkerProcess(ServiceConfigOptions(true, cluster.isPrimary))
|
|
442
|
+
const worker = new WorkerProcess(ServiceConfigOptions(true, cluster.isPrimary));
|
|
443
|
+
worker.SetupServer();
|
|
443
444
|
//StartTestWorker();
|
|
444
445
|
|
|
445
446
|
setTimeout(async () => {
|
|
@@ -521,5 +522,22 @@ if (cluster.isPrimary) {
|
|
|
521
522
|
}
|
|
522
523
|
}, 1000);
|
|
523
524
|
*/
|
|
525
|
+
|
|
526
|
+
worker.redisMessageHandler.emit('GetSystemInformation', {
|
|
527
|
+
group: 'primary'
|
|
528
|
+
}, (response: any) => {
|
|
529
|
+
console.log(`------------------------------------------------------------------------`);
|
|
530
|
+
console.log(response);
|
|
531
|
+
});
|
|
532
|
+
|
|
533
|
+
worker.redisMessageHandler.emitWithError('GetSystemInformation', {
|
|
534
|
+
group: 'primary'
|
|
535
|
+
}, (response: any) => {
|
|
536
|
+
console.log(`************************************************************************`);
|
|
537
|
+
console.log(response);
|
|
538
|
+
}, (error: any) => {
|
|
539
|
+
console.log(chalk.red(`GetSystemInformation Error: [${error}]`));
|
|
540
|
+
});
|
|
541
|
+
|
|
524
542
|
}, 2000);
|
|
525
543
|
}
|
package/src/workerprocessbase.ts
CHANGED
|
@@ -300,6 +300,8 @@ export class WorkerProcessBase extends ServerProcessBase implements IWorkerProce
|
|
|
300
300
|
*/
|
|
301
301
|
// });
|
|
302
302
|
|
|
303
|
+
this.redisMessageHandler.AddGroup('worker');
|
|
304
|
+
|
|
303
305
|
this.WorkerStarted();
|
|
304
306
|
|
|
305
307
|
this.LogInfoMessage(chalk.green(`Worker process:${process.pid} started`));
|