Skip to content

Commit 9a72331

Browse files
authored
Merge pull request #44 from datapartyjs/service-task
Service tasks
2 parents 62e3171 + 4dfea54 commit 9a72331

6 files changed

Lines changed: 279 additions & 22 deletions

File tree

examples/tasks/status-display.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
const debug = require('debug')('dataparty.task.status-update')
2+
3+
const ITask = require('../../src/service/itask')
4+
5+
class StatusDisplayTask extends ITask {
6+
7+
constructor(options){
8+
super({
9+
name: StatusDisplayTask.name,
10+
background: StatusDisplayTask.Config.background,
11+
...options
12+
})
13+
14+
debug('new')
15+
16+
this.duration = 5000
17+
this.timeout = null
18+
}
19+
20+
static get Config(){
21+
return {
22+
background: true,
23+
autostart: true
24+
}
25+
}
26+
27+
async exec(){
28+
29+
this.setTimer()
30+
31+
return this.detach()
32+
}
33+
34+
setTimer(){
35+
this.timeout = setTimeout(this.onTimeout.bind(this), this.duration)
36+
}
37+
38+
onTimeout(){
39+
this.timeout = null
40+
41+
this.context.serviceRunner.taskRunner.printTaskLists()
42+
debug('sleep complete')
43+
44+
this.setTimer()
45+
}
46+
47+
stop(){
48+
if(this.timeout !== null){
49+
clearTimeout(this.timeout)
50+
this.timeout = null
51+
}
52+
}
53+
54+
static get Name(){
55+
return 'status-display'
56+
}
57+
58+
static get Description(){
59+
return 'Status Display'
60+
}
61+
}
62+
63+
module.exports = StatusDisplayTask

examples/test-service-tasks.js

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
const Path = require('path')
2+
const debug = require('debug')('test.server-db')
3+
const Dataparty = require('../src')
4+
5+
const BouncerServerModels = require('@dataparty/bouncer-model')
6+
const BouncerClientModels = require('@dataparty/bouncer-model/dist/bouncer-model.json')
7+
8+
class ExampleTaskService extends Dataparty.IService {
9+
constructor(opts){
10+
super(opts)
11+
12+
this.addTask(Path.join(__dirname,'./tasks/status-display.js'))
13+
}
14+
15+
}
16+
17+
async function main(){
18+
19+
20+
//const uri = 'mongodb://localhost:27017/server-party-test'
21+
//debug('db location', uri)
22+
23+
const path = '/data/datparty/srv-party'
24+
25+
let party = new Dataparty.TingoParty({
26+
path,
27+
model: BouncerClientModels,
28+
serverModels: BouncerServerModels,
29+
config: new Dataparty.Config.JsonFileConfig({basePath: '/data/datparty/'})
30+
})
31+
32+
const service = new ExampleTaskService({ name: '@dataparty/task-example', version: '0.0.1' })
33+
34+
const build = await service.compile(Path.join(__dirname,'/dataparty'), true)
35+
36+
debug('built', Object.keys(build))
37+
38+
const runner = new Dataparty.ServiceRunnerNode({
39+
party, service,
40+
sendFullErrors: false,
41+
useNative: true
42+
})
43+
44+
const host = new Dataparty.ServiceHost({
45+
runner,
46+
trust_proxy: true,
47+
wsEnabled: true,
48+
listenUri: 'http://localhost:8080'
49+
})
50+
51+
await party.start()
52+
await runner.start()
53+
await host.start()
54+
55+
console.log('started')
56+
57+
//process.exit()
58+
}
59+
60+
61+
62+
main().catch(err=>{
63+
console.error(err)
64+
})

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@dataparty/api",
33
"private": false,
4-
"version": "1.2.15",
4+
"version": "1.2.16",
55
"main": "dist/dataparty.js",
66
"frontend": "dist/dataparty-browser.js",
77
"backend": "dist/dataparty.js",
@@ -59,6 +59,7 @@
5959
"dependencies": {
6060
"@dataparty/bouncer-db": "1.0.1",
6161
"@dataparty/crypto": "datapartyjs/dataparty-crypto#parcel-build",
62+
"@dataparty/tasker": "^0.0.2",
6263
"@hapi/joi": "^17.1.1",
6364
"@zeit/ncc": "^0.22.3",
6465
"ajv": "6.9.1",

src/service/iservice.js

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ module.exports = class IService {
2121
middleware: {
2222
pre: {},
2323
post: {}
24-
}
24+
},
25+
tasks: {}
2526
}
2627

2728
this.middleware_order = {
@@ -36,7 +37,8 @@ module.exports = class IService {
3637
middleware: {
3738
pre: {},
3839
post: {}
39-
}
40+
},
41+
tasks: {}
4042
}
4143

4244
this.compiled = {
@@ -55,7 +57,27 @@ module.exports = class IService {
5557
middleware_order: {
5658
pre: [],
5759
post: []
58-
}
60+
},
61+
tasks: {}
62+
}
63+
64+
this.compileSettings = {
65+
// provide a custom cache path or disable caching
66+
cache: false,
67+
// externals to leave as requires of the build
68+
externals: ['debug', '@dataparty/crypto', '@dataparty/tasker', '@hapi/joi', '@hapi/hoek'],
69+
// directory outside of which never to emit assets
70+
//filterAssetBase: process.cwd(), // default
71+
minify: false, // default
72+
sourceMap: true, // default
73+
//sourceMapBasePrefix: '../', // default treats sources as output-relative
74+
// when outputting a sourcemap, automatically include
75+
// source-map-support in the output file (increases output by 32kB).
76+
sourceMapRegister: false, // default
77+
watch: false, // default
78+
v8cache: false, // default
79+
quiet: false, // default
80+
debugLog: false // default
5981
}
6082
}
6183

@@ -112,6 +134,18 @@ module.exports = class IService {
112134
this.constructors.middleware[type][name] = middleware
113135
}
114136

137+
addTask(task_path){
138+
139+
debug('addTask', task_path)
140+
141+
const TaskClass = require(task_path)
142+
143+
const name = TaskClass.Name
144+
145+
this.sources.tasks[name] = task_path
146+
this.constructors.tasks[name] = TaskClass
147+
}
148+
115149

116150
async compile(outputPath, writeFile=true){
117151

@@ -131,11 +165,14 @@ module.exports = class IService {
131165
this.compileMiddleware('post'),
132166
this.compileList('documents'),
133167
this.compileList('endpoints'),
168+
this.compileList('tasks'),
134169
this.compileSchemas()
135170
])
136171

137172
this.compiled.middleware_order = this.middleware_order
138173

174+
this.compiled.compileSettings = this.compileSettings
175+
139176
if(writeFile){
140177
const buildOutput = outputPath+'/'+ this.compiled.package.name.replace('/', '-') +'.dataparty-service.json'
141178
fs.writeFileSync(buildOutput, JSON.stringify(this.compiled, null,2))
@@ -179,24 +216,7 @@ module.exports = class IService {
179216
}
180217

181218
async compileFileTo(input, output){
182-
const { code, map, assets } = await NCC(input, {
183-
// provide a custom cache path or disable caching
184-
cache: false,
185-
// externals to leave as requires of the build
186-
externals: ['debug', '@dataparty/crypto', '@hapi/joi', '@hapi/hoek'],
187-
// directory outside of which never to emit assets
188-
//filterAssetBase: process.cwd(), // default
189-
minify: true, // default
190-
sourceMap: true, // default
191-
//sourceMapBasePrefix: '../', // default treats sources as output-relative
192-
// when outputting a sourcemap, automatically include
193-
// source-map-support in the output file (increases output by 32kB).
194-
sourceMapRegister: false, // default
195-
watch: false, // default
196-
v8cache: false, // default
197-
quiet: false, // default
198-
debugLog: false // default
199-
})
219+
const { code, map, assets } = await NCC(input, this.compileSettings)
200220

201221
debug('compileFileTo', input, '->', output)
202222
debug('\t','code length', Math.round(code.length/1024), 'KB')

src/service/itask.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const debug = require('debug')('dataparty.service.ITask')
2+
const tasker = require('@dataparty/tasker')
3+
4+
5+
module.exports = class ITask extends tasker.Task {
6+
7+
constructor(options){
8+
super(options)
9+
}
10+
11+
static get Name(){
12+
throw new Error('not implemented')
13+
}
14+
15+
static get Description(){
16+
throw new Error('not implemented')
17+
}
18+
19+
static get Config(){
20+
throw new Error('not implemented')
21+
22+
/**
23+
*
24+
* return {
25+
* background: true
26+
* autostart: true
27+
* }
28+
*/
29+
}
30+
31+
static get info(){
32+
return {
33+
Name: this.Name,
34+
Description: this.Description,
35+
Config: this.Config
36+
}
37+
}
38+
}

src/service/service-runner-node.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const EndpointContext = require('./endpoint-context')
88
const DeltaTime = require('../utils/delta-time')
99

1010
const Router = require('origin-router').Router
11+
const Runner = require('@dataparty/tasker').Runner
1112

1213
class ServiceRunnerNode {
1314
constructor({service, party, sendFullErrors=false, useNative=true}){
@@ -18,11 +19,31 @@ class ServiceRunnerNode {
1819

1920
this.middleware = { pre: {}, post: {} }
2021
this.endpoint = {}
22+
this.tasks = {}
2123

2224
this.router = new Router()
25+
this.taskRunner = new Runner()
2326
}
2427

2528
async start(){
29+
30+
debug('starting tasks')
31+
32+
const taskMap = Hoek.reach(this.service, 'compiled.tasks')
33+
//const endpointsLoading = []
34+
for(let name in taskMap){
35+
debug('\t',name)
36+
await this.loadTask(name)
37+
}
38+
39+
debug('tasks ready:')
40+
for(let name in this.tasks){
41+
debug('\t', name)
42+
}
43+
44+
await this.taskRunner.start()
45+
46+
2647
debug('starting endpoints')
2748

2849
const eps = Hoek.reach(this.service, 'compiled.endpoints')
@@ -40,6 +61,56 @@ class ServiceRunnerNode {
4061
}
4162
}
4263

64+
async loadTask(name){
65+
if(this.tasks[name]){
66+
return
67+
}
68+
69+
debug('loadTask', name)
70+
71+
let dt = new DeltaTime().start()
72+
73+
74+
"use strict"
75+
let task=null
76+
77+
let TaskClass = null
78+
79+
if(!this.useNative){
80+
const build = Hoek.reach(this.service, `compiled.tasks.${name}`)
81+
TaskClass = eval(build.code/*, build.map*/)
82+
}
83+
else{
84+
TaskClass = this.service.constructors.tasks[name]
85+
}
86+
87+
task = new TaskClass({
88+
context:{
89+
party: this.party,
90+
serviceRunner: this
91+
}
92+
})
93+
94+
95+
debug('task info', TaskClass.info)
96+
97+
this.tasks[name] = task
98+
99+
if(TaskClass.Config.autostart){
100+
this.taskRunner.addTask(task)
101+
}
102+
103+
104+
dt.end()
105+
debug('loaded task',name,'in',dt.deltaMs,'ms')
106+
}
107+
108+
runTask(name){
109+
const task = this.tasks[name]
110+
111+
this.taskRunner.addTask(task)
112+
}
113+
43114
async loadEndpoint(name){
44115
if(this.endpoint[name]){
45116
return

0 commit comments

Comments
 (0)