@things-factory/edge 8.0.0 → 9.0.0-beta.3
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-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/client/bootstrap.ts +0 -1
- package/client/index.ts +0 -0
- package/client/pages/edge-status-page.ts +0 -173
- package/client/route.ts +0 -7
- package/client/tsconfig.json +0 -11
- package/server/controllers/connect-connections.ts +0 -84
- package/server/controllers/disconnect-connections.ts +0 -77
- package/server/controllers/log-aggregator.ts +0 -14
- package/server/controllers/operato-client.ts +0 -108
- package/server/controllers/run-task.ts +0 -104
- package/server/controllers/sync-connections.ts +0 -89
- package/server/index.ts +0 -17
- package/server/service/connection/connection-query.ts +0 -21
- package/server/service/connection/index.ts +0 -3
- package/server/service/index.ts +0 -19
- package/server/tsconfig.json +0 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/edge",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0-beta.3",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "dist-client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
"migration:create": "node ../../node_modules/typeorm/cli.js migration:create ./server/migrations/migration"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@operato/graphql": "^
|
|
31
|
-
"@operato/shell": "^
|
|
32
|
-
"@things-factory/auth-base": "^
|
|
33
|
-
"@things-factory/env": "^8.0.0",
|
|
34
|
-
"@things-factory/integration-base": "^
|
|
35
|
-
"@things-factory/shell": "^
|
|
30
|
+
"@operato/graphql": "^9.0.0-beta",
|
|
31
|
+
"@operato/shell": "^9.0.0-beta",
|
|
32
|
+
"@things-factory/auth-base": "^9.0.0-beta.3",
|
|
33
|
+
"@things-factory/env": "^8.0.0-beta.4",
|
|
34
|
+
"@things-factory/integration-base": "^9.0.0-beta.3",
|
|
35
|
+
"@things-factory/shell": "^9.0.0-beta.0",
|
|
36
36
|
"cross-fetch": "^3.0.4"
|
|
37
37
|
},
|
|
38
|
-
"gitHead": "
|
|
38
|
+
"gitHead": "1d7e0dd4c88f3c3f3bd311c00e4b1d1542d53634"
|
|
39
39
|
}
|
package/client/bootstrap.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export default function bootstrap() {}
|
package/client/index.ts
DELETED
|
File without changes
|
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import '@operato/data-grist'
|
|
2
|
-
import '@operato/context/ox-context-page-toolbar.js'
|
|
3
|
-
import '@operato/input/ox-input-select-buttons.js'
|
|
4
|
-
|
|
5
|
-
import { PropertyValues, css, html } from 'lit'
|
|
6
|
-
import { customElement, property, query, state } from 'lit/decorators.js'
|
|
7
|
-
import { connect } from 'pwa-helpers/connect-mixin.js'
|
|
8
|
-
import gql from 'graphql-tag'
|
|
9
|
-
|
|
10
|
-
import { store, PageView } from '@operato/shell'
|
|
11
|
-
import { client } from '@operato/graphql'
|
|
12
|
-
import { DataGrist, FetchOption, GristRecord } from '@operato/data-grist'
|
|
13
|
-
import { i18next, localize } from '@operato/i18n'
|
|
14
|
-
import { openPopup } from '@operato/layout'
|
|
15
|
-
import { CommonHeaderStyles, ScrollbarStyles } from '@operato/styles'
|
|
16
|
-
import { isMobileDevice } from '@operato/utils'
|
|
17
|
-
|
|
18
|
-
@customElement('edge-status-page')
|
|
19
|
-
export class EdgeStatusPage extends connect(store)(localize(i18next)(PageView)) {
|
|
20
|
-
static styles = [
|
|
21
|
-
ScrollbarStyles,
|
|
22
|
-
CommonHeaderStyles,
|
|
23
|
-
css`
|
|
24
|
-
:host {
|
|
25
|
-
display: flex;
|
|
26
|
-
flex-direction: column;
|
|
27
|
-
|
|
28
|
-
overflow: hidden;
|
|
29
|
-
|
|
30
|
-
--grid-header-padding: 2px 0 2px 9px;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
ox-grist {
|
|
34
|
-
overflow-y: auto;
|
|
35
|
-
flex: 1;
|
|
36
|
-
}
|
|
37
|
-
`
|
|
38
|
-
]
|
|
39
|
-
|
|
40
|
-
@state() private gristConfig: any
|
|
41
|
-
@state() private mode: 'CARD' | 'GRID' | 'LIST' = isMobileDevice() ? 'CARD' : 'GRID'
|
|
42
|
-
@state() private state?: string[]
|
|
43
|
-
|
|
44
|
-
@query('ox-grist') private grist!: DataGrist
|
|
45
|
-
|
|
46
|
-
get context() {
|
|
47
|
-
return {
|
|
48
|
-
title: i18next.t('title.edge-status'),
|
|
49
|
-
search: {
|
|
50
|
-
handler: (search: string) => {
|
|
51
|
-
this.grist.searchText = search
|
|
52
|
-
},
|
|
53
|
-
value: this.grist?.searchText || ''
|
|
54
|
-
},
|
|
55
|
-
filter: {
|
|
56
|
-
handler: () => {
|
|
57
|
-
this.grist.toggleHeadroom()
|
|
58
|
-
}
|
|
59
|
-
},
|
|
60
|
-
help: 'edge/edge-status',
|
|
61
|
-
actions: [],
|
|
62
|
-
toolbar: false
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
render() {
|
|
67
|
-
const mode = this.mode || (isMobileDevice() ? 'LIST' : 'GRID')
|
|
68
|
-
|
|
69
|
-
return html`
|
|
70
|
-
<ox-grist .mode=${mode} .config=${this.gristConfig} .fetchHandler=${this.fetchHandler.bind(this)}>
|
|
71
|
-
<div slot="headroom" class="header">
|
|
72
|
-
<div class="title">${i18next.t('label.connections')}</div>
|
|
73
|
-
|
|
74
|
-
<ox-context-page-toolbar class="actions" .context=${this.context}></ox-context-page-toolbar>
|
|
75
|
-
</div>
|
|
76
|
-
</ox-grist>
|
|
77
|
-
`
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async pageInitialized(lifecycle) {
|
|
81
|
-
this.gristConfig = {
|
|
82
|
-
list: {
|
|
83
|
-
fields: ['name', 'description'],
|
|
84
|
-
details: ['active', 'updatedAt']
|
|
85
|
-
},
|
|
86
|
-
columns: [
|
|
87
|
-
{ type: 'gutter', gutterName: 'sequence' },
|
|
88
|
-
{
|
|
89
|
-
type: 'string',
|
|
90
|
-
name: 'domain',
|
|
91
|
-
header: i18next.t('field.domain'),
|
|
92
|
-
record: {
|
|
93
|
-
renderer: value => value.name
|
|
94
|
-
},
|
|
95
|
-
width: 200
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
type: 'string',
|
|
99
|
-
name: 'type',
|
|
100
|
-
header: i18next.t('field.type'),
|
|
101
|
-
width: 150
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
type: 'string',
|
|
105
|
-
name: 'name',
|
|
106
|
-
header: i18next.t('field.name'),
|
|
107
|
-
width: 150
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
type: 'string',
|
|
111
|
-
name: 'description',
|
|
112
|
-
header: i18next.t('field.description'),
|
|
113
|
-
width: 200
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
type: 'checkbox',
|
|
117
|
-
name: 'active',
|
|
118
|
-
label: true,
|
|
119
|
-
header: i18next.t('field.active'),
|
|
120
|
-
width: 60
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
type: 'string',
|
|
124
|
-
name: 'state',
|
|
125
|
-
label: true,
|
|
126
|
-
header: i18next.t('field.status'),
|
|
127
|
-
width: 100
|
|
128
|
-
}
|
|
129
|
-
],
|
|
130
|
-
rows: {
|
|
131
|
-
appendable: false,
|
|
132
|
-
selectable: false,
|
|
133
|
-
handlers: {}
|
|
134
|
-
},
|
|
135
|
-
pagination: { infinite: true },
|
|
136
|
-
sorters: []
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async pageUpdated(changes: any, lifecycle: any) {
|
|
141
|
-
if (this.active) {
|
|
142
|
-
// do something here when this page just became as active
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async fetchHandler() {
|
|
147
|
-
const response = await client.query({
|
|
148
|
-
query: gql`
|
|
149
|
-
query {
|
|
150
|
-
responses: connectionsOnEdge {
|
|
151
|
-
domain {
|
|
152
|
-
id
|
|
153
|
-
name
|
|
154
|
-
subdomain
|
|
155
|
-
}
|
|
156
|
-
id
|
|
157
|
-
type
|
|
158
|
-
name
|
|
159
|
-
description
|
|
160
|
-
endpoint
|
|
161
|
-
active
|
|
162
|
-
state
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
`
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
return {
|
|
169
|
-
total: response.data.responses.length || 0,
|
|
170
|
-
records: response.data.responses || []
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
}
|
package/client/route.ts
DELETED
package/client/tsconfig.json
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import gql from 'graphql-tag'
|
|
2
|
-
|
|
3
|
-
import { logger } from '@things-factory/env'
|
|
4
|
-
import { Connection, ConnectionManager, ConnectionStatus } from '@things-factory/integration-base'
|
|
5
|
-
|
|
6
|
-
import { getOperatoClient } from './operato-client'
|
|
7
|
-
import { LogAggregator } from './log-aggregator'
|
|
8
|
-
|
|
9
|
-
export async function initConnectConnectionsSubscription() {
|
|
10
|
-
const client = await getOperatoClient()
|
|
11
|
-
|
|
12
|
-
const subscription = client.subscribe({
|
|
13
|
-
query: gql`
|
|
14
|
-
subscription {
|
|
15
|
-
connectConnections {
|
|
16
|
-
domain {
|
|
17
|
-
id
|
|
18
|
-
name
|
|
19
|
-
subdomain
|
|
20
|
-
}
|
|
21
|
-
id
|
|
22
|
-
type
|
|
23
|
-
name
|
|
24
|
-
description
|
|
25
|
-
endpoint
|
|
26
|
-
active
|
|
27
|
-
state
|
|
28
|
-
params
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
`
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
subscription.subscribe({
|
|
35
|
-
next: async subscription => {
|
|
36
|
-
const connections = subscription.data?.connectConnections || []
|
|
37
|
-
await connectConnections(
|
|
38
|
-
connections.map(connection => {
|
|
39
|
-
try {
|
|
40
|
-
const params = JSON.parse(connection.params)
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
...connection,
|
|
44
|
-
params
|
|
45
|
-
}
|
|
46
|
-
} catch (e) {
|
|
47
|
-
return {
|
|
48
|
-
...connection,
|
|
49
|
-
params: null
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
)
|
|
54
|
-
},
|
|
55
|
-
error: error => {
|
|
56
|
-
logger.error(`operato subscription error: ${error}`)
|
|
57
|
-
},
|
|
58
|
-
complete: () => {
|
|
59
|
-
logger.info(`operato subscription complete`)
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async function connectConnections(connections: Connection[]) {
|
|
65
|
-
console.log('connectConnections ...', connections)
|
|
66
|
-
|
|
67
|
-
connections.forEach(connection => connectConnection(connection))
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function connectConnection(connection: Connection) {
|
|
71
|
-
const { type } = connection
|
|
72
|
-
|
|
73
|
-
const old = ConnectionManager.getConnectionInstance(connection)
|
|
74
|
-
if (old) {
|
|
75
|
-
ConnectionManager.removeConnectionInstance(connection)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const connector = ConnectionManager.getConnector(type)
|
|
79
|
-
if (!connector) {
|
|
80
|
-
return
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
await connector.connect(connection)
|
|
84
|
-
}
|
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import gql from 'graphql-tag'
|
|
2
|
-
|
|
3
|
-
import { logger } from '@things-factory/env'
|
|
4
|
-
import { Connection, ConnectionManager, ConnectionStatus } from '@things-factory/integration-base'
|
|
5
|
-
|
|
6
|
-
import { getOperatoClient } from './operato-client'
|
|
7
|
-
import { LogAggregator } from './log-aggregator'
|
|
8
|
-
|
|
9
|
-
export async function initDisconnectConnectionsSubscription() {
|
|
10
|
-
const client = await getOperatoClient()
|
|
11
|
-
|
|
12
|
-
const subscription = client.subscribe({
|
|
13
|
-
query: gql`
|
|
14
|
-
subscription {
|
|
15
|
-
disconnectConnections {
|
|
16
|
-
domain {
|
|
17
|
-
id
|
|
18
|
-
name
|
|
19
|
-
subdomain
|
|
20
|
-
}
|
|
21
|
-
id
|
|
22
|
-
type
|
|
23
|
-
name
|
|
24
|
-
description
|
|
25
|
-
endpoint
|
|
26
|
-
active
|
|
27
|
-
state
|
|
28
|
-
params
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
`
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
subscription.subscribe({
|
|
35
|
-
next: async subscription => {
|
|
36
|
-
const connections = subscription.data?.disconnectConnections || []
|
|
37
|
-
await disconnectConnections(
|
|
38
|
-
connections.map(connection => {
|
|
39
|
-
try {
|
|
40
|
-
const params = JSON.parse(connection.params)
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
...connection,
|
|
44
|
-
params
|
|
45
|
-
}
|
|
46
|
-
} catch (e) {
|
|
47
|
-
return {
|
|
48
|
-
...connection,
|
|
49
|
-
params: null
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
)
|
|
54
|
-
},
|
|
55
|
-
error: error => {
|
|
56
|
-
logger.error(`operato subscription error: ${error}`)
|
|
57
|
-
},
|
|
58
|
-
complete: () => {
|
|
59
|
-
logger.info(`operato subscription complete`)
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
async function disconnectConnections(connections: Connection[]) {
|
|
65
|
-
console.log('disconnectConnections ...', connections)
|
|
66
|
-
|
|
67
|
-
connections.forEach(connection => disconnectConnection(connection))
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async function disconnectConnection(connection: Connection) {
|
|
71
|
-
const { type } = connection
|
|
72
|
-
|
|
73
|
-
const old = ConnectionManager.getConnectionInstance(connection)
|
|
74
|
-
if (old) {
|
|
75
|
-
ConnectionManager.removeConnectionInstance(connection)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import 'cross-fetch/polyfill'
|
|
2
|
-
|
|
3
|
-
import { ApolloClient, InMemoryCache, createHttpLink, split } from '@apollo/client/core'
|
|
4
|
-
import { setContext } from '@apollo/client/link/context'
|
|
5
|
-
|
|
6
|
-
import WebSocket from 'ws'
|
|
7
|
-
import { createClient } from 'graphql-ws'
|
|
8
|
-
import { GraphQLWsLink } from '@apollo/client/link/subscriptions'
|
|
9
|
-
import { getMainDefinition } from '@apollo/client/utilities'
|
|
10
|
-
|
|
11
|
-
import { Domain, getRepository } from '@things-factory/shell'
|
|
12
|
-
import { User } from '@things-factory/auth-base'
|
|
13
|
-
import { config } from '@things-factory/env'
|
|
14
|
-
|
|
15
|
-
const OperatoConfig = config.get('operato', {})
|
|
16
|
-
const { endpoint: uri, domain: subdomain, authKey } = OperatoConfig
|
|
17
|
-
|
|
18
|
-
const defaultOptions: any = {
|
|
19
|
-
watchQuery: {
|
|
20
|
-
fetchPolicy: 'no-cache',
|
|
21
|
-
errorPolicy: 'ignore'
|
|
22
|
-
},
|
|
23
|
-
query: {
|
|
24
|
-
fetchPolicy: 'no-cache', //'network-only'
|
|
25
|
-
errorPolicy: 'all'
|
|
26
|
-
},
|
|
27
|
-
mutate: {
|
|
28
|
-
errorPolicy: 'all'
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
var client
|
|
33
|
-
|
|
34
|
-
export async function getOperatoClient() {
|
|
35
|
-
if (!client) {
|
|
36
|
-
if (!authKey || !subdomain) {
|
|
37
|
-
throw new Error('some operato config missing.')
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const domain = await getRepository(Domain).findOne({
|
|
41
|
-
where: {
|
|
42
|
-
subdomain: 'system'
|
|
43
|
-
}
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
const user = await getRepository(User).findOne({
|
|
47
|
-
where: {
|
|
48
|
-
id: domain.owner
|
|
49
|
-
}
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
const httpLink = createHttpLink({
|
|
53
|
-
uri: uri
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
/*
|
|
57
|
-
CHECKPOINT:
|
|
58
|
-
1. GraphqQLWsLink를 사용하면 setContext를 통한 추가 헤더 설정이 무시됩니다.
|
|
59
|
-
따라서, GraphQLWsLink를 사용하려면, connectionParams를 통해 헤더를 설정해야 합니다.
|
|
60
|
-
|
|
61
|
-
2. 서버에서 실행시, webSocketImpl을 명시적으로 지정해야 합니다.
|
|
62
|
-
*/
|
|
63
|
-
const wsLink = new GraphQLWsLink(
|
|
64
|
-
createClient({
|
|
65
|
-
url: uri.replace(/^http/, 'ws'),
|
|
66
|
-
keepAlive: 10_000,
|
|
67
|
-
retryAttempts: 1_000_000,
|
|
68
|
-
shouldRetry: e => true,
|
|
69
|
-
webSocketImpl: WebSocket,
|
|
70
|
-
connectionParams: {
|
|
71
|
-
headers: {
|
|
72
|
-
'x-things-factory-domain': subdomain,
|
|
73
|
-
authorization: authKey ? `Bearer ${authKey}` : ''
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
const splitLink = split(
|
|
80
|
-
({ query }) => {
|
|
81
|
-
const def = getMainDefinition(query)
|
|
82
|
-
return def.kind === 'OperationDefinition' && def.operation === 'subscription'
|
|
83
|
-
},
|
|
84
|
-
wsLink,
|
|
85
|
-
setContext((_, { headers }) => {
|
|
86
|
-
return {
|
|
87
|
-
headers: {
|
|
88
|
-
...headers,
|
|
89
|
-
'x-things-factory-domain': subdomain,
|
|
90
|
-
authorization: authKey ? `Bearer ${authKey}` : ''
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}).concat(httpLink)
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
const cache = new InMemoryCache({
|
|
97
|
-
addTypename: false
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
client = new ApolloClient({
|
|
101
|
-
defaultOptions,
|
|
102
|
-
cache,
|
|
103
|
-
link: splitLink
|
|
104
|
-
})
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return client
|
|
108
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import gql from 'graphql-tag'
|
|
2
|
-
|
|
3
|
-
import { createLogger, format } from 'winston'
|
|
4
|
-
|
|
5
|
-
import { logger } from '@things-factory/env'
|
|
6
|
-
import { Step, Context, TaskRegistry } from '@things-factory/integration-base/'
|
|
7
|
-
|
|
8
|
-
import { getOperatoClient } from './operato-client'
|
|
9
|
-
import { LogAggregator } from './log-aggregator'
|
|
10
|
-
|
|
11
|
-
export async function initRunTaskSubscription() {
|
|
12
|
-
const client = await getOperatoClient()
|
|
13
|
-
|
|
14
|
-
const subscription = client.subscribe({
|
|
15
|
-
query: gql`
|
|
16
|
-
subscription {
|
|
17
|
-
runTask {
|
|
18
|
-
id
|
|
19
|
-
step {
|
|
20
|
-
task
|
|
21
|
-
connection
|
|
22
|
-
params
|
|
23
|
-
}
|
|
24
|
-
context {
|
|
25
|
-
domain {
|
|
26
|
-
id
|
|
27
|
-
name
|
|
28
|
-
subdomain
|
|
29
|
-
}
|
|
30
|
-
data
|
|
31
|
-
variables
|
|
32
|
-
lng
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
`
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
subscription.subscribe({
|
|
40
|
-
next: async subscription => {
|
|
41
|
-
const { id, step, context }: { id: string; step: Step; context: Context } = subscription?.data?.runTask || {}
|
|
42
|
-
logger.info(`received run-task request: %s, %s, %s`, id, step, context)
|
|
43
|
-
await runTask(id, step, context)
|
|
44
|
-
},
|
|
45
|
-
error: error => {
|
|
46
|
-
logger.error(`operato subscription for runTask error: ${error}`)
|
|
47
|
-
},
|
|
48
|
-
complete: () => {
|
|
49
|
-
logger.info(`operato subscription for runTask complete`)
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function runTask(id: string, step: Step, context: Context) {
|
|
55
|
-
var handler = TaskRegistry.getTaskHandler(step.task)
|
|
56
|
-
if (!handler) {
|
|
57
|
-
throw new Error(`no task handler for step '${step.name}'(${step.id})`)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
var error
|
|
61
|
-
|
|
62
|
-
const logAggregator = new LogAggregator({})
|
|
63
|
-
|
|
64
|
-
const logger = createLogger({
|
|
65
|
-
format: format.combine(
|
|
66
|
-
format.timestamp(),
|
|
67
|
-
format.printf(({ timestamp, level, message, stack }) => `${timestamp} ${level}: ${stack || message}`)
|
|
68
|
-
),
|
|
69
|
-
transports: [logAggregator]
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
try {
|
|
73
|
-
var out: any = await handler(
|
|
74
|
-
{
|
|
75
|
-
...step,
|
|
76
|
-
params: JSON.parse(step.params)
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
...context,
|
|
80
|
-
logger
|
|
81
|
-
}
|
|
82
|
-
)
|
|
83
|
-
} catch (e) {
|
|
84
|
-
error = e?.stack || e
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const client = await getOperatoClient()
|
|
88
|
-
|
|
89
|
-
await client.mutate({
|
|
90
|
-
mutation: gql`
|
|
91
|
-
mutation RunTaskCallback($result: RunTaskCallbackInput!) {
|
|
92
|
-
runTaskCallback(result: $result)
|
|
93
|
-
}
|
|
94
|
-
`,
|
|
95
|
-
variables: {
|
|
96
|
-
result: {
|
|
97
|
-
id,
|
|
98
|
-
out,
|
|
99
|
-
logs: logAggregator.formatResults(),
|
|
100
|
-
error
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
})
|
|
104
|
-
}
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
import gql from 'graphql-tag'
|
|
2
|
-
|
|
3
|
-
import { logger } from '@things-factory/env'
|
|
4
|
-
import { Connection, ConnectionManager, ConnectionStatus } from '@things-factory/integration-base'
|
|
5
|
-
|
|
6
|
-
import { getOperatoClient } from './operato-client'
|
|
7
|
-
import { LogAggregator } from './log-aggregator'
|
|
8
|
-
|
|
9
|
-
export async function initSyncConnectionsSubscription() {
|
|
10
|
-
const client = await getOperatoClient()
|
|
11
|
-
|
|
12
|
-
const subscription = client.subscribe({
|
|
13
|
-
query: gql`
|
|
14
|
-
subscription {
|
|
15
|
-
syncConnections {
|
|
16
|
-
domain {
|
|
17
|
-
id
|
|
18
|
-
name
|
|
19
|
-
subdomain
|
|
20
|
-
}
|
|
21
|
-
id
|
|
22
|
-
type
|
|
23
|
-
name
|
|
24
|
-
description
|
|
25
|
-
endpoint
|
|
26
|
-
active
|
|
27
|
-
state
|
|
28
|
-
params
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
`
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
subscription.subscribe({
|
|
35
|
-
next: async subscription => {
|
|
36
|
-
const connections = subscription.data?.syncConnections || []
|
|
37
|
-
await syncConnections(
|
|
38
|
-
connections.map(connection => {
|
|
39
|
-
try {
|
|
40
|
-
const params = JSON.parse(connection.params)
|
|
41
|
-
|
|
42
|
-
return {
|
|
43
|
-
// domain,
|
|
44
|
-
...connection,
|
|
45
|
-
params
|
|
46
|
-
}
|
|
47
|
-
} catch (e) {
|
|
48
|
-
return {
|
|
49
|
-
// domain,
|
|
50
|
-
...connection,
|
|
51
|
-
params: null
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
})
|
|
55
|
-
)
|
|
56
|
-
},
|
|
57
|
-
error: error => {
|
|
58
|
-
logger.error(`operato subscription error: ${error}`)
|
|
59
|
-
},
|
|
60
|
-
complete: () => {
|
|
61
|
-
logger.info(`operato subscription complete`)
|
|
62
|
-
}
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
async function syncConnections(connections: Connection[]) {
|
|
67
|
-
console.log('syncConnections ...', connections)
|
|
68
|
-
|
|
69
|
-
if (connections.length == 0) {
|
|
70
|
-
return
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const domain = connections[0]?.domain
|
|
74
|
-
const oldConnections = ConnectionManager.getConnectionInstances(domain)
|
|
75
|
-
Object.values(oldConnections).forEach(old => ConnectionManager.removeConnectionInstance(old))
|
|
76
|
-
|
|
77
|
-
connections.forEach(connection => syncConnection(connection))
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
async function syncConnection(connection: Connection) {
|
|
81
|
-
const { type, state } = connection
|
|
82
|
-
|
|
83
|
-
var connector = ConnectionManager.getConnector(type)
|
|
84
|
-
if (!connector) {
|
|
85
|
-
return
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
await connector.connect(connection)
|
|
89
|
-
}
|