@things-factory/integration-base 6.2.117 → 6.2.120

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.
Files changed (29) hide show
  1. package/dist-server/controllers/index.js +5 -0
  2. package/dist-server/controllers/index.js.map +1 -0
  3. package/dist-server/controllers/scenario-controller.js +87 -0
  4. package/dist-server/controllers/scenario-controller.js.map +1 -0
  5. package/dist-server/engine/connector/oracle-connector.js +79 -31
  6. package/dist-server/engine/connector/oracle-connector.js.map +1 -1
  7. package/dist-server/index.js +1 -0
  8. package/dist-server/index.js.map +1 -1
  9. package/dist-server/restful/unstable/run-scenario.js.map +1 -1
  10. package/dist-server/restful/unstable/start-scenario.js +1 -1
  11. package/dist-server/restful/unstable/start-scenario.js.map +1 -1
  12. package/dist-server/restful/unstable/stop-scenario.js +1 -1
  13. package/dist-server/restful/unstable/stop-scenario.js.map +1 -1
  14. package/dist-server/service/scenario-instance/scenario-instance-mutation.js +4 -71
  15. package/dist-server/service/scenario-instance/scenario-instance-mutation.js.map +1 -1
  16. package/dist-server/service/scenario-instance/scenario-instance-type.js.map +1 -1
  17. package/dist-server/tsconfig.tsbuildinfo +1 -1
  18. package/openapi/unstable/scenario.yaml +100 -100
  19. package/openapi/unstable.yaml +11 -11
  20. package/package.json +7 -7
  21. package/server/controllers/index.ts +1 -0
  22. package/server/controllers/scenario-controller.ts +116 -0
  23. package/server/engine/connector/oracle-connector.ts +92 -34
  24. package/server/index.ts +1 -0
  25. package/server/restful/unstable/run-scenario.ts +0 -1
  26. package/server/restful/unstable/start-scenario.ts +1 -1
  27. package/server/restful/unstable/stop-scenario.ts +1 -1
  28. package/server/service/scenario-instance/scenario-instance-mutation.ts +10 -121
  29. package/server/service/scenario-instance/scenario-instance-type.ts +5 -8
@@ -5,7 +5,7 @@ import { Connector } from '../types'
5
5
  import { InputConnection } from '../../service/connection/connection-type'
6
6
 
7
7
  try {
8
- var Client = require('oracledb')
8
+ var oracledb = require('oracledb')
9
9
  } catch (err) {
10
10
  logger.error('oracledb module loading failed')
11
11
  }
@@ -17,7 +17,7 @@ export class OracleConnector implements Connector {
17
17
  ConnectionManager.logger.info('oracle-connector connections are ready')
18
18
  }
19
19
 
20
- async connect(connection: InputConnection) {
20
+ async recreatePool(connection: InputConnection) {
21
21
  const {
22
22
  name,
23
23
  endpoint,
@@ -25,12 +25,13 @@ export class OracleConnector implements Connector {
25
25
  domain
26
26
  } = connection
27
27
 
28
- if (!Client) {
28
+ if (!oracledb) {
29
29
  throw new Error('oracledb module loading failed')
30
30
  }
31
31
 
32
32
  const poolAlias = `${domain.name}-${name}`
33
- const client = await Client.createPool({
33
+ await oracledb.getPool(poolAlias).close(10)
34
+ await oracledb.createPool({
34
35
  user,
35
36
  password,
36
37
  // when oracle not using default port must add connection string with port like localhost:port
@@ -41,49 +42,106 @@ export class OracleConnector implements Connector {
41
42
  poolAlias
42
43
  })
43
44
 
45
+ ConnectionManager.logger.info(`Oracle Database(${connection.name}:${database}) at ${endpoint} recreated.`)
46
+ }
47
+
48
+ async connect(connection: InputConnection) {
49
+ const {
50
+ name,
51
+ endpoint,
52
+ params: { user, password, database, poolMin, poolMax, poolIncrement },
53
+ domain
54
+ } = connection
55
+
56
+ if (!oracledb) {
57
+ throw new Error('oracledb module loading failed')
58
+ }
59
+
60
+ const poolAlias = `${domain.name}-${name}`
61
+
62
+ var enableStatistics = true
63
+ const pool = await oracledb.createPool({
64
+ user,
65
+ password,
66
+ // when oracle not using default port must add connection string with port like localhost:port
67
+ connectString: `${endpoint.trim()}/${database}`,
68
+ poolMin,
69
+ poolMax,
70
+ poolIncrement,
71
+ poolAlias,
72
+ enableStatistics
73
+ })
44
74
 
45
75
  ConnectionManager.addConnectionInstance(connection, {
46
76
  query: async (query, params) => {
47
- const connection = await Client.getConnection(poolAlias)
48
- const result = (
49
- await connection.execute(query, params, {
50
- outFormat: Client.OBJECT
51
- })
52
- ).rows
53
- await connection.close()
54
- return result
77
+ let dbConnection: any = {}
78
+ let taskResult: any = {}
79
+ try {
80
+ dbConnection = await oracledb.getConnection(poolAlias)
81
+
82
+ taskResult = (
83
+ await dbConnection.execute(query, params, {
84
+ outFormat: oracledb.OBJECT
85
+ })
86
+ ).rows
87
+ } catch (e) {
88
+ if (e.name === 'Error' && e.message.includes('NJS-040')) {
89
+ await this.recreatePool(connection)
90
+ }
91
+ throw e
92
+ }
93
+ finally {
94
+ await dbConnection.close()
95
+ }
96
+ return taskResult
55
97
 
56
98
  },
57
99
  execute: async (procedure, params) => {
58
- // TODO: need to check if this is available when procedure string is a common query.
59
- procedure = `BEGIN
60
- ${procedure}
61
- END;`
62
- const connection = await Client.getConnection(poolAlias)
63
- const result = await connection.execute(procedure, params, {
64
- outFormat: Client.OBJECT
65
- })
66
-
67
- var taskResult = {}
68
- let paramKeys = Object.keys(params)
69
-
70
- for (const paramKey of paramKeys) {
71
- if (params[paramKey].dir === Client?.BIND_OUT) {
72
- if (params[paramKey].type === Client?.CURSOR) {
73
- const resultSetTemp = result.outBinds[paramKey]
74
- taskResult[paramKey] = await resultSetTemp.getRows()
75
- await resultSetTemp.close()
76
- } else {
77
- taskResult[paramKey] = result.outBinds[paramKey]
100
+ let dbConnection: any = {}
101
+ let taskResult: any = {}
102
+ try {
103
+ // TODO: need to check if this is available when procedure string is a common query.
104
+ procedure = `BEGIN
105
+ ${procedure}
106
+ END;`
107
+ dbConnection = await oracledb.getConnection(poolAlias)
108
+
109
+ // console.log('\n************* stat after get ****************')
110
+ // await oracledb.getPool(poolAlias).logStatistics()
111
+
112
+ const result = await dbConnection.execute(procedure, params, {
113
+ outFormat: oracledb.OBJECT
114
+ })
115
+
116
+ let paramKeys = Object.keys(params)
117
+
118
+ for (const paramKey of paramKeys) {
119
+ if (params[paramKey].dir === oracledb?.BIND_OUT) {
120
+ if (params[paramKey].type === oracledb?.CURSOR) {
121
+ const resultSetTemp = result.outBinds[paramKey]
122
+ taskResult[paramKey] = await resultSetTemp.getRows()
123
+ await resultSetTemp.close()
124
+ } else {
125
+ taskResult[paramKey] = result.outBinds[paramKey]
126
+ }
78
127
  }
79
128
  }
129
+ } catch (e) {
130
+ if (e.name === 'Error' && e.message.includes('NJS-040')) {
131
+ await this.recreatePool(connection)
132
+ }
133
+ throw e
80
134
  }
135
+ finally {
136
+ await dbConnection.close()
81
137
 
82
- await connection.close()
138
+ // console.log('\n************* stat after close ****************')
139
+ // await oracledb.getPool(poolAlias).logStatistics()
140
+ }
83
141
  return taskResult
84
142
  },
85
143
  close: async () => {
86
- await Client.getPool(poolAlias).close(10)
144
+ await oracledb.getPool(poolAlias).close(10)
87
145
  }
88
146
  })
89
147
 
package/server/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './migrations'
2
2
  export * from './engine'
3
+ export * from './controllers'
3
4
  export * from './service'
4
5
 
5
6
  import './routes'
@@ -1,7 +1,6 @@
1
1
  import gql from 'graphql-tag'
2
2
 
3
3
  import { restfulApiRouter as router } from '@things-factory/api'
4
- import { ScenarioInstanceStatus } from '../../service/scenario-instance/scenario-instance-type'
5
4
 
6
5
  const debug = require('debug')('things-factory:integration-base:restful:unstable:run-scenario')
7
6
 
@@ -12,7 +12,7 @@ router.post('/unstable/start-scenario/:scenarioName', async (context, next) => {
12
12
 
13
13
  context.body = await client.mutate({
14
14
  mutation: gql`
15
- mutation($instanceName: String, $scenarioName: String!, $variables: Object) {
15
+ mutation ($instanceName: String, $scenarioName: String!, $variables: Object) {
16
16
  startScenario(instanceName: $instanceName, scenarioName: $scenarioName, variables: $variables) {
17
17
  instanceName
18
18
  scenarioName
@@ -11,7 +11,7 @@ router.post('/unstable/stop-scenario/:instanceName', async (context, next) => {
11
11
 
12
12
  context.body = await client.mutate({
13
13
  mutation: gql`
14
- mutation($instanceName: String!) {
14
+ mutation ($instanceName: String!) {
15
15
  stopScenario(instanceName: $instanceName) {
16
16
  instanceName
17
17
  scenarioName
@@ -1,35 +1,14 @@
1
1
  import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'
2
2
 
3
- import { getRepository, Domain, GraphqlLocalClient, ScalarObject } from '@things-factory/shell'
3
+ import { ScalarObject } from '@things-factory/shell'
4
4
 
5
- import { ScenarioEngine } from '../../engine'
6
- import { Scenario } from '../scenario/scenario'
7
5
  import { ScenarioInstance } from './scenario-instance-type'
8
- import { PrivilegeObject, User, checkPermission } from '@things-factory/auth-base'
9
- import { Step } from '../step/step-type'
10
6
 
11
- const debug = require('debug')('things-factory:integration-base:scenario-instance-mutation')
12
-
13
- async function findScenario(
14
- scenarioName: string,
15
- domain: Domain
16
- ): Promise<{ name: string; steps: Step[]; domain: Domain; privilege?: PrivilegeObject }> {
17
- var repository = getRepository(Scenario)
18
-
19
- var scenario = await repository.findOne({
20
- where: { domain: { id: domain.id }, name: scenarioName },
21
- relations: ['domain', 'steps', 'creator', 'updater']
22
- })
23
-
24
- if (!scenario && domain.parentId) {
25
- scenario = await repository.findOne({
26
- where: { domain: { id: domain.parentId }, name: scenarioName },
27
- relations: ['domain', 'steps', 'creator', 'updater']
28
- })
29
- }
30
-
31
- return scenario as any
32
- }
7
+ import {
8
+ runScenario as controllerRunScenario,
9
+ startScenario as controllerStartScenario,
10
+ stopScenario as controllerStopScenario
11
+ } from '../../controllers/scenario-controller'
33
12
 
34
13
  @Resolver(ScenarioInstance)
35
14
  export class ScenarioInstanceMutation {
@@ -42,42 +21,7 @@ export class ScenarioInstanceMutation {
42
21
  @Arg('variables', type => ScalarObject, { nullable: true }) variables: any,
43
22
  @Ctx() context: ResolverContext
44
23
  ): Promise<ScenarioInstance> {
45
- const { domain, user, lng, unsafeIP, prohibitedPrivileges } = context.state
46
-
47
- debug('runScenario', scenarioName, instanceName, variables)
48
-
49
- var scenario = await findScenario(scenarioName, domain)
50
-
51
- if (!scenario) {
52
- throw new Error(
53
- context.t('error.scenario not found', {
54
- scenario: scenarioName
55
- })
56
- )
57
- }
58
-
59
- if (!(await checkPermission(scenario.privilege, user, domain, unsafeIP, prohibitedPrivileges))) {
60
- const { category, privilege } = scenario.privilege || {}
61
- throw new Error(
62
- `Unauthorized! ${
63
- category && privilege ? category + ':' + privilege + ' privilege' : 'ownership granted'
64
- } required`
65
- )
66
- }
67
-
68
- /* 시나리오 인스턴스를 생성한다. */
69
- instanceName = instanceName || scenarioName + '-' + String(Date.now())
70
- var instance = new ScenarioInstance(instanceName, scenario, {
71
- domain,
72
- user,
73
- lng,
74
- variables,
75
- client: GraphqlLocalClient.client
76
- })
77
-
78
- await instance.run()
79
-
80
- return instance
24
+ return await controllerRunScenario(instanceName, scenarioName, variables, context)
81
25
  }
82
26
 
83
27
  @Mutation(returns => ScenarioInstance, { description: 'To start new scenario instance' })
@@ -87,66 +31,11 @@ export class ScenarioInstanceMutation {
87
31
  @Arg('variables', type => ScalarObject, { nullable: true }) variables: any,
88
32
  @Ctx() context: ResolverContext
89
33
  ): Promise<ScenarioInstance> {
90
- const { domain, user, lng, unsafeIP, prohibitedPrivileges } = context.state
91
-
92
- debug('startScenario', instanceName, scenarioName, variables)
93
-
94
- var scenario = await findScenario(scenarioName, domain)
95
-
96
- if (!scenario) {
97
- throw new Error(
98
- context.t('error.scenario not found', {
99
- scenario: scenarioName
100
- })
101
- )
102
- }
103
-
104
- if (!(await checkPermission(scenario.privilege, user, domain, unsafeIP, prohibitedPrivileges))) {
105
- const { category, privilege } = scenario.privilege || {}
106
- throw new Error(
107
- `Unauthorized! ${
108
- category && privilege ? category + ':' + privilege + ' privilege' : 'ownership granted'
109
- } required`
110
- )
111
- }
112
-
113
- instanceName = instanceName || scenarioName
114
- return await ScenarioEngine.load(instanceName, scenario, { domain, user, lng, variables })
34
+ return await controllerStartScenario(instanceName, scenarioName, variables, context)
115
35
  }
116
36
 
117
37
  @Mutation(returns => ScenarioInstance, { nullable: true, description: 'To start new scenario instance' })
118
- async stopScenario(
119
- @Arg('instanceName', { nullable: true }) instanceName: string,
120
- @Ctx() context: ResolverContext
121
- ): Promise<ScenarioInstance | undefined> {
122
- const { domain, user, unsafeIP, prohibitedPrivileges } = context.state
123
-
124
- debug('stopScenario', instanceName)
125
-
126
- var scenarioInstance = ScenarioEngine.getScenarioInstance(domain, instanceName)
127
-
128
- if (!scenarioInstance) {
129
- debug('stopScenario', `ScenarioInstance(${instanceName}) Not Found.`)
130
- throw new Error(
131
- context.t('error.scenario instance not found', {
132
- instance: instanceName
133
- })
134
- )
135
- }
136
-
137
- var scenario = await findScenario(scenarioInstance.scenarioName, domain)
138
-
139
- if (!(await checkPermission(scenario.privilege, user, domain, unsafeIP, prohibitedPrivileges))) {
140
- const { category, privilege } = scenario.privilege || {}
141
- throw new Error(
142
- `Unauthorized! ${
143
- category && privilege ? category + ':' + privilege + ' privilege' : 'ownership granted'
144
- } required`
145
- )
146
- }
147
-
148
- await ScenarioEngine.unload(domain, instanceName)
149
-
150
- return scenarioInstance
38
+ async stopScenario(@Arg('instanceName', { nullable: true }) instanceName: string, @Ctx() context: ResolverContext): Promise<ScenarioInstance | undefined> {
39
+ return await controllerStopScenario(instanceName, context)
151
40
  }
152
41
  }
@@ -125,7 +125,7 @@ export class ScenarioInstance {
125
125
  timestamp: Date
126
126
 
127
127
  @Field({ nullable: true })
128
- private message: string
128
+ public message: string
129
129
 
130
130
  private steps: Step[]
131
131
  private rounds: number = 0
@@ -267,10 +267,7 @@ export class ScenarioInstance {
267
267
  this.context.logger.error(ex.message ? ex.message : ex)
268
268
 
269
269
  debug('failed to run ', `[ Domain: ${domain.name}, Scenario: ${scenarioName} ]\n`, ex)
270
- this.setState(
271
- ScenarioInstanceStatus.HALTED,
272
- typeof message == 'object' ? JSON.stringify(message, null, 2) : message
273
- )
270
+ this.setState(ScenarioInstanceStatus.HALTED, typeof message == 'object' ? JSON.stringify(message, null, 2) : message)
274
271
 
275
272
  throw ex
276
273
  }
@@ -376,9 +373,9 @@ export class ScenarioInstance {
376
373
  return
377
374
  }
378
375
 
379
- this.message = `${this.instanceName}:[state changed] ${ScenarioInstanceStatus[this.getState()]} => ${
380
- ScenarioInstanceStatus[state]
381
- }${message ? ' caused by ' + util.inspect(message, false, 2, true) : ''}`
376
+ this.message = `${this.instanceName}:[state changed] ${ScenarioInstanceStatus[this.getState()]} => ${ScenarioInstanceStatus[state]}${
377
+ message ? ' caused by ' + util.inspect(message, false, 2, true) : ''
378
+ }`
382
379
 
383
380
  this.context.state = state
384
381