feat(task): merge custom data into properties

BREAKING CHANGE.

This makes these entries mutable during the life of the task.
This commit is contained in:
Julien Fontanet 2023-06-05 15:39:04 +02:00
parent fe7f0db81f
commit 1da05e239d
9 changed files with 33 additions and 46 deletions

View File

@ -2,10 +2,8 @@
import { Task } from '@vates/task'
const task = new Task({
// data in this object will be sent along the *start* event
//
// property names should be chosen as not to clash with properties used by `Task` or `combineEvents`
data: {
// this object will be sent in the *start* event
properties: {
name: 'my task',
},
@ -16,7 +14,7 @@ const task = new Task({
// this function is called each time this task or one of it's subtasks change state
const { id, timestamp, type } = event
if (type === 'start') {
const { name, parentId } = event
const { name, parentId, properties } = event
} else if (type === 'end') {
const { result, status } = event
} else if (type === 'info' || type === 'warning') {

View File

@ -18,10 +18,8 @@ npm install --save @vates/task
import { Task } from '@vates/task'
const task = new Task({
// data in this object will be sent along the *start* event
//
// property names should be chosen as not to clash with properties used by `Task` or `combineEvents`
data: {
// this object will be sent in the *start* event
properties: {
name: 'my task',
},
@ -32,7 +30,7 @@ const task = new Task({
// this function is called each time this task or one of it's subtasks change state
const { id, timestamp, type } = event
if (type === 'start') {
const { name, parentId } = event
const { name, parentId, properties } = event
} else if (type === 'end') {
const { result, status } = event
} else if (type === 'info' || type === 'warning') {

View File

@ -4,36 +4,18 @@ const assert = require('node:assert').strict
const noop = Function.prototype
function omit(source, keys, target = { __proto__: null }) {
for (const key of Object.keys(source)) {
if (!keys.has(key)) {
target[key] = source[key]
}
}
return target
}
const IGNORED_START_PROPS = new Set([
'end',
'infos',
'properties',
'result',
'status',
'tasks',
'timestamp',
'type',
'warnings',
])
exports.makeOnProgress = function ({ onRootTaskEnd = noop, onRootTaskStart = noop, onTaskUpdate = noop }) {
const taskLogs = new Map()
return function onProgress(event) {
const { id, type } = event
let taskLog
if (type === 'start') {
taskLog = omit(event, IGNORED_START_PROPS)
taskLog.start = event.timestamp
taskLog.status = 'pending'
taskLog = {
id,
properties: { __proto__: null, ...event.properties },
start: event.timestamp,
status: 'pending',
}
taskLogs.set(id, taskLog)
const { parentId } = event

View File

@ -11,7 +11,7 @@ describe('makeOnProgress()', function () {
const events = []
let log
const task = new Task({
data: { name: 'task' },
properties: { name: 'task' },
onProgress: makeOnProgress({
onRootTaskStart(log_) {
assert.equal(log, undefined)
@ -38,8 +38,13 @@ describe('makeOnProgress()', function () {
assert.equal(events[i++], 'onRootTaskStart')
assert.equal(events[i++], 'onTaskUpdate')
assert.equal(log.id, task.id)
assert.equal(log.properties.name, 'task')
assert(Math.abs(log.start - Date.now()) < 10)
Task.set('name', 'new name')
assert.equal(events[i++], 'onTaskUpdate')
assert.equal(log.properties.name, 'new name')
Task.set('progress', 0)
assert.equal(events[i++], 'onTaskUpdate')
assert.equal(log.properties.progress, 0)
@ -48,9 +53,9 @@ describe('makeOnProgress()', function () {
assert.equal(events[i++], 'onTaskUpdate')
assert.deepEqual(log.infos, [{ data: {}, message: 'foo' }])
await Task.run({ data: { name: 'subtask' } }, () => {
await Task.run({ properties: { name: 'subtask' } }, () => {
assert.equal(events[i++], 'onTaskUpdate')
assert.equal(log.tasks[0].name, 'subtask')
assert.equal(log.tasks[0].properties.name, 'subtask')
Task.warning('bar', {})
assert.equal(events[i++], 'onTaskUpdate')

View File

@ -83,8 +83,8 @@ exports.Task = class Task {
return this.#status
}
constructor({ data = {}, onProgress } = {}) {
this.#startData = data
constructor({ properties, onProgress } = {}) {
this.#startData = { properties }
if (onProgress !== undefined) {
this.#onProgress = onProgress

View File

@ -15,7 +15,7 @@ function assertEvent(task, expected, eventIndex = -1) {
assert.equal(typeof actual.id, 'string')
assert.equal(typeof actual.timestamp, 'number')
for (const keys of Object.keys(expected)) {
assert.equal(actual[keys], expected[keys])
assert.deepEqual(actual[keys], expected[keys])
}
}
@ -30,10 +30,10 @@ function createTask(opts) {
describe('Task', function () {
describe('contructor', function () {
it('data properties are passed to the start event', async function () {
const data = { foo: 0, bar: 1 }
const task = createTask({ data })
const properties = { foo: 0, bar: 1 }
const task = createTask({ properties })
await task.run(noop)
assertEvent(task, { ...data, type: 'start' }, 0)
assertEvent(task, { type: 'start', properties }, 0)
})
})

View File

@ -134,7 +134,7 @@ export default class Tasks extends EventEmitter {
create({ name, objectId, type }) {
const tasks = this.#tasks
const task = new Task({ data: { name, objectId, type }, onProgress: this.#onProgress })
const task = new Task({ properties: { name, objectId, type }, onProgress: this.#onProgress })
// Use a compact, sortable, string representation of the creation date
//

View File

@ -28,5 +28,6 @@
<!--packages-start-->
- @vates/nbd-client patch
- @vates/task minor
<!--packages-end-->

View File

@ -155,11 +155,14 @@ const FINISHED_TASKS_COLUMNS = [
const XO_TASKS_COLUMNS = [
{
itemRenderer: task => task.name,
itemRenderer: task => task.properties?.name ?? task.name,
name: _('name'),
},
{
itemRenderer: task => (task.objectId === undefined ? null : renderXoItemFromId(task.objectId, { link: true })),
itemRenderer: task => {
const { objectId } = task.properties ?? task
return objectId === undefined ? null : renderXoItemFromId(task.objectId, { link: true })
},
name: _('object'),
},
{