UNPKG

6.54 kBtext/coffeescriptView Raw
1_ = require 'lodash'
2path = require 'path'
3glob = require 'glob'
4MeshbluHTTP = require 'meshblu-http'
5moment = require 'moment'
6debug = require('debug')('slurry-core:configure-handler')
7
8THIRTY_SECONDS = 30 * 1000
9
10class ConfigureHandler
11 constructor: ({ @slurrySpreader, @defaultConfiguration, @configurationsPath, @meshbluConfig }={}) ->
12 throw new Error 'ConfigureHandler requires configurationsPath' unless @configurationsPath?
13 throw new Error 'ConfigureHandler requires slurrySpreader' unless @slurrySpreader?
14 @configurations = @_getConfigurations()
15 @_slurryStreams = {}
16 @slurrySpreader.on 'create', @_onSlurryCreate
17 @slurrySpreader.on 'destroy', @_onSlurryDestroy
18 @slurrySpreader.on 'onlineUntil', @_updateOnlineUntil
19
20 configureSchema: (callback) =>
21 callback null, @_configureSchemaFromConfigurations @configurations
22
23 formSchema: (callback) =>
24 callback null, @_formSchemaFromConfigurations @configurations
25
26 onConfigure: ({auth, userDeviceUuid, encrypted, config}, callback) =>
27 selectedConfiguration = config.schemas?.selected?.configure ? @defaultConfiguration ? 'Default'
28 slurry = {
29 auth
30 selectedConfiguration
31 encrypted
32 config
33 uuid: userDeviceUuid
34 }
35 return @slurrySpreader.remove(slurry, callback) if config.slurry?.disabled
36 @slurrySpreader.add slurry, callback
37
38 _configureSchemaFromConfigurations: (configurations) =>
39 _.mapValues configurations, @_configureSchemaFromJob
40
41 _configureSchemaFromJob: (job, key) =>
42 configure = _.cloneDeep job.configure
43 _.set configure, 'x-form-schema.angular', "configure.#{key}.angular"
44 slurryProp = _.get configure, 'properties.slurry'
45 newSlurryProp = _.merge slurryProp, @_generateConfigureSlurry()
46 _.set configure, 'properties.slurry', newSlurryProp
47 configure.required = _.union ['metadata'], configure.required
48 return configure
49
50 _destroySlurry: ({ uuid }) =>
51 slurryStream = @_slurryStreams[uuid]
52 return unless slurryStream?
53 slurryStream.removeListener 'close', slurryStream.__slurryOnClose
54 slurryStream.removeListener 'error', slurryStream.__slurryOnError
55 delete slurryStream.__slurryOnClose
56 throw new Error 'slurryStream must implement destroy method' unless _.isFunction slurryStream?.destroy
57 slurryStream.destroy()
58 delete @_slurryStreams[uuid]
59
60 _onSlurryCreate: (slurry) =>
61 {
62 uuid
63 selectedConfiguration
64 config
65 encrypted
66 auth
67 } = slurry
68 slurryConfiguration = @configurations[selectedConfiguration]
69 return unless slurryConfiguration?
70
71 @_destroySlurry { uuid }
72 return if config.slurry?.disabled
73
74 slurryConfiguration.action {encrypted, auth, userDeviceUuid: uuid}, config, (error, slurryStream) =>
75 @_updateStatusDeviceWithError {auth, userDeviceUuid: uuid, error} if error?
76
77 if error?
78 console.error error.stack
79 @slurrySpreader.delay {uuid, timeout:THIRTY_SECONDS}, _.noop if error.code == 401
80 @slurrySpreader.close {uuid}, _.noop
81 return
82
83 return @_onSlurryDelay slurry unless slurryStream?
84
85 slurryStream.__slurryOnClose = =>
86 @_onSlurryClose slurry
87
88 slurryStream.__slurryOnError = (error) =>
89 console.error error.stack
90 @_updateStatusDeviceWithError {auth, userDeviceUuid: uuid, error}
91 @_destroySlurry slurry
92
93 slurryStream.__slurryOnDelay = (error, timeout=THIRTY_SECONDS) =>
94 throw new Error 'parameter "error" must pass _.isError' unless _.isError error
95 console.error error.stack
96 @_updateStatusDeviceWithError {auth, userDeviceUuid: uuid, error}
97 @_onSlurryDelay {uuid, timeout}
98
99 throw new Error 'slurryStream must implement on method' unless _.isFunction slurryStream?.on
100 slurryStream.on 'close', slurryStream.__slurryOnClose
101 slurryStream.on 'error', slurryStream.__slurryOnError
102 slurryStream.on 'delay', slurryStream.__slurryOnDelay
103 @_slurryStreams[uuid] = slurryStream
104
105 _onSlurryDelay: ({uuid, timeout}) =>
106 @_destroySlurry { uuid }
107 @slurrySpreader.delay {uuid, timeout}, (error) =>
108 @_slurryStreams[uuid].destroy?()
109 return console.error error if error?
110
111 _onSlurryDestroy: ({ uuid }) =>
112 @_destroySlurry { uuid }
113
114 _onSlurryClose: (slurry) =>
115 @slurrySpreader.close slurry, _.noop
116
117 _formSchemaFromConfigurations: (configurations) =>
118 return {
119 configure: _.mapValues configurations, 'form'
120 }
121
122 _generateConfigureSlurry: =>
123 return {
124 type: 'object'
125 required: ['disabled']
126 properties:
127 disabled:
128 type: 'boolean'
129 title: 'Disabled'
130 description: 'Disable streaming'
131 }
132
133 _getConfigurations: =>
134 dirnames = glob.sync path.join(@configurationsPath, '/*/')
135 configurations = {}
136 _.each dirnames, (dir) =>
137 key = _.upperFirst _.camelCase path.basename dir
138 try
139 configurations[key] = require dir
140 catch error
141 console.error error.stack
142
143 return configurations
144
145 _updateOnlineUntil: ({slurry, onlineUntil}) =>
146 {auth, config} = slurry
147 {statusDevice} = config
148 @_addStatusDeviceRef {auth, statusDevice} unless @_hasStatusDeviceRef config
149 meshblu = new MeshbluHTTP _.defaults auth, @meshbluConfig
150 meshblu.update statusDevice, {
151 'status.onlineUntil': onlineUntil
152 }, (error) => console.error error.stack if error?
153
154 _hasStatusDeviceRef: (config) =>
155 return config?.status?.$ref?
156
157 _addStatusDeviceRef: ({auth, statusDevice}) =>
158 meshblu = new MeshbluHTTP _.defaults auth, @meshbluConfig
159 meshblu.update auth.uuid, {
160 status: $ref: "meshbludevice://#{statusDevice}/#/status"
161 }, (error) => console.error error.stack if error?
162
163 _updateStatusDeviceWithError: ({auth, userDeviceUuid, error}, callback=_.noop) =>
164 debug '_updateStatusDeviceWithError', userDeviceUuid, error
165
166 meshblu = new MeshbluHTTP _.defaults auth, @meshbluConfig
167 meshblu.device userDeviceUuid, (newError, {statusDevice}={}) =>
168 debug '_updateStatusDeviceWithError:statusDevice', newError?.message, statusDevice
169 return callback newError if newError?
170 return callback() unless statusDevice?
171 update =
172 $push:
173 errors:
174 $each: [
175 date: moment.utc().format()
176 code: error.code ? 500
177 message: error.message
178 ]
179 $slice: -99
180 meshblu.updateDangerously statusDevice, update, callback
181
182module.exports = ConfigureHandler