@adminforth/background-jobs 1.12.1 → 1.13.1
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/build.log +2 -2
- package/custom/JobInfoPopup.vue +104 -4
- package/custom/JobsList.vue +31 -5
- package/dist/custom/JobInfoPopup.vue +104 -4
- package/dist/custom/JobsList.vue +31 -5
- package/dist/index.js +22 -2
- package/index.ts +26 -3
- package/package.json +1 -1
package/build.log
CHANGED
|
@@ -13,5 +13,5 @@ custom/tsconfig.json
|
|
|
13
13
|
custom/useBackgroundJobApi.ts
|
|
14
14
|
custom/utils.ts
|
|
15
15
|
|
|
16
|
-
sent
|
|
17
|
-
total size is
|
|
16
|
+
sent 22,184 bytes received 172 bytes 44,712.00 bytes/sec
|
|
17
|
+
total size is 21,551 speedup is 0.96
|
package/custom/JobInfoPopup.vue
CHANGED
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
:meta="job.customComponent"
|
|
55
55
|
:getJobTasks="getJobTasks"
|
|
56
56
|
:job="job"
|
|
57
|
+
:subscribeToJobStateFields="subscribeToJobStateFields"
|
|
58
|
+
:subscribeToJobTaskFields="subscribeToJobTaskFields"
|
|
57
59
|
/>
|
|
58
60
|
</template>
|
|
59
61
|
|
|
@@ -67,12 +69,15 @@ import { getTimeAgoString, callAdminForthApi, getCustomComponent} from '@/utils'
|
|
|
67
69
|
import { useI18n } from 'vue-i18n';
|
|
68
70
|
import StateToIcon from './StateToIcon.vue';
|
|
69
71
|
import { useAdminforth } from '@/adminforth';
|
|
70
|
-
import { watch } from 'vue';
|
|
72
|
+
import { onBeforeUnmount, ref, watch } from 'vue';
|
|
73
|
+
import websocket from '@/websocket';
|
|
74
|
+
import { useBackgroundJobApi } from './useBackgroundJobApi';
|
|
71
75
|
|
|
72
76
|
|
|
73
77
|
const { t } = useI18n();
|
|
74
78
|
|
|
75
79
|
const adminforth = useAdminforth();
|
|
80
|
+
const jobStore = useBackgroundJobApi();
|
|
76
81
|
|
|
77
82
|
const props = defineProps<{
|
|
78
83
|
job: IJob;
|
|
@@ -82,6 +87,90 @@ const props = defineProps<{
|
|
|
82
87
|
closeModal: () => void;
|
|
83
88
|
}>();
|
|
84
89
|
|
|
90
|
+
type JobTask = {
|
|
91
|
+
state: Record<string, any>;
|
|
92
|
+
status: string;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
type JobStateFieldUpdate = {
|
|
96
|
+
jobId: string;
|
|
97
|
+
fieldName: string;
|
|
98
|
+
value: any;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
type TaskStateFieldUpdate = JobStateFieldUpdate & {
|
|
102
|
+
taskIndex: number;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const jobTasks = ref<JobTask[]>([]);
|
|
106
|
+
const subscriptionCleanups = new Set<() => void>();
|
|
107
|
+
|
|
108
|
+
function getUniqueFieldNames(fieldNames: string[]): string[] {
|
|
109
|
+
return Array.from(new Set(fieldNames.filter((fieldName) => typeof fieldName === 'string' && fieldName.length > 0)));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function createStateFieldSubscription(
|
|
113
|
+
fieldNames: string[],
|
|
114
|
+
pathFactory: (fieldName: string) => string,
|
|
115
|
+
callback: (data: any) => void,
|
|
116
|
+
) {
|
|
117
|
+
const paths = getUniqueFieldNames(fieldNames).map(pathFactory);
|
|
118
|
+
for (const path of paths) {
|
|
119
|
+
websocket.subscribe(path, callback);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const unsubscribe = () => {
|
|
123
|
+
for (const path of paths) {
|
|
124
|
+
websocket.unsubscribe(path);
|
|
125
|
+
}
|
|
126
|
+
subscriptionCleanups.delete(unsubscribe);
|
|
127
|
+
};
|
|
128
|
+
subscriptionCleanups.add(unsubscribe);
|
|
129
|
+
return unsubscribe;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function handleJobStateFieldUpdate(data: JobStateFieldUpdate) {
|
|
133
|
+
if (data.jobId !== props.job.id) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
props.job.state[data.fieldName] = data.value;
|
|
138
|
+
if (jobStore.currentJob?.id === props.job.id) {
|
|
139
|
+
jobStore.updateCurrentJob({
|
|
140
|
+
state: {
|
|
141
|
+
...props.job.state,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function handleTaskStateFieldUpdate(data: TaskStateFieldUpdate) {
|
|
148
|
+
if (data.jobId !== props.job.id || !jobTasks.value[data.taskIndex]) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
jobTasks.value[data.taskIndex].state = {
|
|
153
|
+
...jobTasks.value[data.taskIndex].state,
|
|
154
|
+
[data.fieldName]: data.value,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function subscribeToJobStateFields(fieldNames: string[]) {
|
|
159
|
+
return createStateFieldSubscription(
|
|
160
|
+
fieldNames,
|
|
161
|
+
(fieldName) => `/background-jobs-state-update/${props.job.id}/${encodeURIComponent(fieldName)}`,
|
|
162
|
+
handleJobStateFieldUpdate,
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function subscribeToJobTaskFields(fieldNames: string[]) {
|
|
167
|
+
return createStateFieldSubscription(
|
|
168
|
+
fieldNames,
|
|
169
|
+
(fieldName) => `/background-jobs-task-state-update/${props.job.id}/${encodeURIComponent(fieldName)}`,
|
|
170
|
+
handleTaskStateFieldUpdate,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
85
174
|
async function cancelJob() {
|
|
86
175
|
// Implement job cancellation logic here
|
|
87
176
|
const isConfirmed = await adminforth.confirm({ message: t('Are you sure you want to cancel this job?') });
|
|
@@ -111,7 +200,7 @@ async function cancelJob() {
|
|
|
111
200
|
|
|
112
201
|
|
|
113
202
|
|
|
114
|
-
async function getJobTasks(limit: number = 10, offset: number = 0): Promise<
|
|
203
|
+
async function getJobTasks(limit: number = 10, offset: number = 0): Promise<JobTask[]> {
|
|
115
204
|
try {
|
|
116
205
|
const res = await callAdminForthApi({
|
|
117
206
|
path: `/plugin/${props.meta.pluginInstanceId}/get-tasks`,
|
|
@@ -123,7 +212,12 @@ async function getJobTasks(limit: number = 10, offset: number = 0): Promise<{sta
|
|
|
123
212
|
},
|
|
124
213
|
});
|
|
125
214
|
if (res.ok) {
|
|
126
|
-
|
|
215
|
+
const tasks = res.data.tasks as JobTask[];
|
|
216
|
+
const startIndex = offset || 0;
|
|
217
|
+
for (let taskIndex = 0; taskIndex < tasks.length; taskIndex++) {
|
|
218
|
+
jobTasks.value[startIndex + taskIndex] = tasks[taskIndex];
|
|
219
|
+
}
|
|
220
|
+
return jobTasks.value.slice(startIndex, startIndex + tasks.length);
|
|
127
221
|
} else {
|
|
128
222
|
console.error('Error fetching job tasks:', res.error);
|
|
129
223
|
return [];
|
|
@@ -147,6 +241,12 @@ watch(
|
|
|
147
241
|
{ immediate: true }
|
|
148
242
|
);
|
|
149
243
|
|
|
244
|
+
onBeforeUnmount(() => {
|
|
245
|
+
for (const unsubscribe of Array.from(subscriptionCleanups)) {
|
|
246
|
+
unsubscribe();
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
150
250
|
|
|
151
251
|
|
|
152
|
-
</script>
|
|
252
|
+
</script>
|
package/custom/JobsList.vue
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
class="p-4"
|
|
6
6
|
v-for="job in props.jobs" :key="job.id"
|
|
7
7
|
:beforeCloseFunction="onBeforeClose"
|
|
8
|
-
:beforeOpenFunction="onBeforeOpen"
|
|
8
|
+
:beforeOpenFunction="() => onBeforeOpen(job)"
|
|
9
9
|
removeFromDomOnClose
|
|
10
10
|
>
|
|
11
11
|
<template #trigger>
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
</div>
|
|
31
31
|
</template>
|
|
32
32
|
<JobInfoPopup
|
|
33
|
-
|
|
33
|
+
v-if="loadedJobs[job.id]"
|
|
34
|
+
:job="loadedJobs[job.id]"
|
|
34
35
|
:meta="meta"
|
|
35
36
|
:closeModal="closeModal"
|
|
36
37
|
/>
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
|
|
43
44
|
<script setup lang="ts">
|
|
44
45
|
import type { IJob } from './utils';
|
|
45
|
-
import { getTimeAgoString } from '@/utils';
|
|
46
|
+
import { callAdminForthApi, getTimeAgoString } from '@/utils';
|
|
46
47
|
import { ProgressBar, Modal } from '@/afcl';
|
|
47
48
|
import JobInfoPopup from './JobInfoPopup.vue';
|
|
48
49
|
import StateToIcon from './StateToIcon.vue';
|
|
@@ -78,9 +79,34 @@ const props = defineProps<{
|
|
|
78
79
|
|
|
79
80
|
|
|
80
81
|
const isModalOpen = ref(false);
|
|
82
|
+
const loadedJobs = ref<Record<string, IJob>>({});
|
|
81
83
|
|
|
82
|
-
function onBeforeOpen() {
|
|
84
|
+
async function onBeforeOpen(job: IJob) {
|
|
83
85
|
props.closeDropdown();
|
|
86
|
+
try {
|
|
87
|
+
const res = await callAdminForthApi({
|
|
88
|
+
path: `/plugin/get-background-job-info`,
|
|
89
|
+
method: 'POST',
|
|
90
|
+
body: { jobId: job.id },
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (res?.ok && res.job) {
|
|
94
|
+
loadedJobs.value[job.id] = res.job;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log('[background-jobs] failed to load full job info', {
|
|
99
|
+
jobId: job.id,
|
|
100
|
+
response: res,
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.log('[background-jobs] failed to load full job info', {
|
|
104
|
+
error,
|
|
105
|
+
jobId: job.id,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
loadedJobs.value[job.id] = job;
|
|
84
110
|
}
|
|
85
111
|
|
|
86
112
|
function onBeforeClose() {
|
|
@@ -88,4 +114,4 @@ function onBeforeClose() {
|
|
|
88
114
|
}
|
|
89
115
|
|
|
90
116
|
|
|
91
|
-
</script>
|
|
117
|
+
</script>
|
|
@@ -54,6 +54,8 @@
|
|
|
54
54
|
:meta="job.customComponent"
|
|
55
55
|
:getJobTasks="getJobTasks"
|
|
56
56
|
:job="job"
|
|
57
|
+
:subscribeToJobStateFields="subscribeToJobStateFields"
|
|
58
|
+
:subscribeToJobTaskFields="subscribeToJobTaskFields"
|
|
57
59
|
/>
|
|
58
60
|
</template>
|
|
59
61
|
|
|
@@ -67,12 +69,15 @@ import { getTimeAgoString, callAdminForthApi, getCustomComponent} from '@/utils'
|
|
|
67
69
|
import { useI18n } from 'vue-i18n';
|
|
68
70
|
import StateToIcon from './StateToIcon.vue';
|
|
69
71
|
import { useAdminforth } from '@/adminforth';
|
|
70
|
-
import { watch } from 'vue';
|
|
72
|
+
import { onBeforeUnmount, ref, watch } from 'vue';
|
|
73
|
+
import websocket from '@/websocket';
|
|
74
|
+
import { useBackgroundJobApi } from './useBackgroundJobApi';
|
|
71
75
|
|
|
72
76
|
|
|
73
77
|
const { t } = useI18n();
|
|
74
78
|
|
|
75
79
|
const adminforth = useAdminforth();
|
|
80
|
+
const jobStore = useBackgroundJobApi();
|
|
76
81
|
|
|
77
82
|
const props = defineProps<{
|
|
78
83
|
job: IJob;
|
|
@@ -82,6 +87,90 @@ const props = defineProps<{
|
|
|
82
87
|
closeModal: () => void;
|
|
83
88
|
}>();
|
|
84
89
|
|
|
90
|
+
type JobTask = {
|
|
91
|
+
state: Record<string, any>;
|
|
92
|
+
status: string;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
type JobStateFieldUpdate = {
|
|
96
|
+
jobId: string;
|
|
97
|
+
fieldName: string;
|
|
98
|
+
value: any;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
type TaskStateFieldUpdate = JobStateFieldUpdate & {
|
|
102
|
+
taskIndex: number;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const jobTasks = ref<JobTask[]>([]);
|
|
106
|
+
const subscriptionCleanups = new Set<() => void>();
|
|
107
|
+
|
|
108
|
+
function getUniqueFieldNames(fieldNames: string[]): string[] {
|
|
109
|
+
return Array.from(new Set(fieldNames.filter((fieldName) => typeof fieldName === 'string' && fieldName.length > 0)));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function createStateFieldSubscription(
|
|
113
|
+
fieldNames: string[],
|
|
114
|
+
pathFactory: (fieldName: string) => string,
|
|
115
|
+
callback: (data: any) => void,
|
|
116
|
+
) {
|
|
117
|
+
const paths = getUniqueFieldNames(fieldNames).map(pathFactory);
|
|
118
|
+
for (const path of paths) {
|
|
119
|
+
websocket.subscribe(path, callback);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const unsubscribe = () => {
|
|
123
|
+
for (const path of paths) {
|
|
124
|
+
websocket.unsubscribe(path);
|
|
125
|
+
}
|
|
126
|
+
subscriptionCleanups.delete(unsubscribe);
|
|
127
|
+
};
|
|
128
|
+
subscriptionCleanups.add(unsubscribe);
|
|
129
|
+
return unsubscribe;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function handleJobStateFieldUpdate(data: JobStateFieldUpdate) {
|
|
133
|
+
if (data.jobId !== props.job.id) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
props.job.state[data.fieldName] = data.value;
|
|
138
|
+
if (jobStore.currentJob?.id === props.job.id) {
|
|
139
|
+
jobStore.updateCurrentJob({
|
|
140
|
+
state: {
|
|
141
|
+
...props.job.state,
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function handleTaskStateFieldUpdate(data: TaskStateFieldUpdate) {
|
|
148
|
+
if (data.jobId !== props.job.id || !jobTasks.value[data.taskIndex]) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
jobTasks.value[data.taskIndex].state = {
|
|
153
|
+
...jobTasks.value[data.taskIndex].state,
|
|
154
|
+
[data.fieldName]: data.value,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function subscribeToJobStateFields(fieldNames: string[]) {
|
|
159
|
+
return createStateFieldSubscription(
|
|
160
|
+
fieldNames,
|
|
161
|
+
(fieldName) => `/background-jobs-state-update/${props.job.id}/${encodeURIComponent(fieldName)}`,
|
|
162
|
+
handleJobStateFieldUpdate,
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function subscribeToJobTaskFields(fieldNames: string[]) {
|
|
167
|
+
return createStateFieldSubscription(
|
|
168
|
+
fieldNames,
|
|
169
|
+
(fieldName) => `/background-jobs-task-state-update/${props.job.id}/${encodeURIComponent(fieldName)}`,
|
|
170
|
+
handleTaskStateFieldUpdate,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
85
174
|
async function cancelJob() {
|
|
86
175
|
// Implement job cancellation logic here
|
|
87
176
|
const isConfirmed = await adminforth.confirm({ message: t('Are you sure you want to cancel this job?') });
|
|
@@ -111,7 +200,7 @@ async function cancelJob() {
|
|
|
111
200
|
|
|
112
201
|
|
|
113
202
|
|
|
114
|
-
async function getJobTasks(limit: number = 10, offset: number = 0): Promise<
|
|
203
|
+
async function getJobTasks(limit: number = 10, offset: number = 0): Promise<JobTask[]> {
|
|
115
204
|
try {
|
|
116
205
|
const res = await callAdminForthApi({
|
|
117
206
|
path: `/plugin/${props.meta.pluginInstanceId}/get-tasks`,
|
|
@@ -123,7 +212,12 @@ async function getJobTasks(limit: number = 10, offset: number = 0): Promise<{sta
|
|
|
123
212
|
},
|
|
124
213
|
});
|
|
125
214
|
if (res.ok) {
|
|
126
|
-
|
|
215
|
+
const tasks = res.data.tasks as JobTask[];
|
|
216
|
+
const startIndex = offset || 0;
|
|
217
|
+
for (let taskIndex = 0; taskIndex < tasks.length; taskIndex++) {
|
|
218
|
+
jobTasks.value[startIndex + taskIndex] = tasks[taskIndex];
|
|
219
|
+
}
|
|
220
|
+
return jobTasks.value.slice(startIndex, startIndex + tasks.length);
|
|
127
221
|
} else {
|
|
128
222
|
console.error('Error fetching job tasks:', res.error);
|
|
129
223
|
return [];
|
|
@@ -147,6 +241,12 @@ watch(
|
|
|
147
241
|
{ immediate: true }
|
|
148
242
|
);
|
|
149
243
|
|
|
244
|
+
onBeforeUnmount(() => {
|
|
245
|
+
for (const unsubscribe of Array.from(subscriptionCleanups)) {
|
|
246
|
+
unsubscribe();
|
|
247
|
+
}
|
|
248
|
+
});
|
|
249
|
+
|
|
150
250
|
|
|
151
251
|
|
|
152
|
-
</script>
|
|
252
|
+
</script>
|
package/dist/custom/JobsList.vue
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
class="p-4"
|
|
6
6
|
v-for="job in props.jobs" :key="job.id"
|
|
7
7
|
:beforeCloseFunction="onBeforeClose"
|
|
8
|
-
:beforeOpenFunction="onBeforeOpen"
|
|
8
|
+
:beforeOpenFunction="() => onBeforeOpen(job)"
|
|
9
9
|
removeFromDomOnClose
|
|
10
10
|
>
|
|
11
11
|
<template #trigger>
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
</div>
|
|
31
31
|
</template>
|
|
32
32
|
<JobInfoPopup
|
|
33
|
-
|
|
33
|
+
v-if="loadedJobs[job.id]"
|
|
34
|
+
:job="loadedJobs[job.id]"
|
|
34
35
|
:meta="meta"
|
|
35
36
|
:closeModal="closeModal"
|
|
36
37
|
/>
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
|
|
43
44
|
<script setup lang="ts">
|
|
44
45
|
import type { IJob } from './utils';
|
|
45
|
-
import { getTimeAgoString } from '@/utils';
|
|
46
|
+
import { callAdminForthApi, getTimeAgoString } from '@/utils';
|
|
46
47
|
import { ProgressBar, Modal } from '@/afcl';
|
|
47
48
|
import JobInfoPopup from './JobInfoPopup.vue';
|
|
48
49
|
import StateToIcon from './StateToIcon.vue';
|
|
@@ -78,9 +79,34 @@ const props = defineProps<{
|
|
|
78
79
|
|
|
79
80
|
|
|
80
81
|
const isModalOpen = ref(false);
|
|
82
|
+
const loadedJobs = ref<Record<string, IJob>>({});
|
|
81
83
|
|
|
82
|
-
function onBeforeOpen() {
|
|
84
|
+
async function onBeforeOpen(job: IJob) {
|
|
83
85
|
props.closeDropdown();
|
|
86
|
+
try {
|
|
87
|
+
const res = await callAdminForthApi({
|
|
88
|
+
path: `/plugin/get-background-job-info`,
|
|
89
|
+
method: 'POST',
|
|
90
|
+
body: { jobId: job.id },
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (res?.ok && res.job) {
|
|
94
|
+
loadedJobs.value[job.id] = res.job;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
console.log('[background-jobs] failed to load full job info', {
|
|
99
|
+
jobId: job.id,
|
|
100
|
+
response: res,
|
|
101
|
+
});
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.log('[background-jobs] failed to load full job info', {
|
|
104
|
+
error,
|
|
105
|
+
jobId: job.id,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
loadedJobs.value[job.id] = job;
|
|
84
110
|
}
|
|
85
111
|
|
|
86
112
|
function onBeforeClose() {
|
|
@@ -88,4 +114,4 @@ function onBeforeClose() {
|
|
|
88
114
|
}
|
|
89
115
|
|
|
90
116
|
|
|
91
|
-
</script>
|
|
117
|
+
</script>
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,9 @@ import pLimit from 'p-limit';
|
|
|
13
13
|
import { Level } from 'level';
|
|
14
14
|
import fs from 'fs/promises';
|
|
15
15
|
import { Mutex } from 'async-mutex';
|
|
16
|
+
function encodeStateFieldName(fieldName) {
|
|
17
|
+
return encodeURIComponent(fieldName);
|
|
18
|
+
}
|
|
16
19
|
export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
17
20
|
constructor(options) {
|
|
18
21
|
super(options, import.meta.url);
|
|
@@ -170,6 +173,23 @@ export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
|
170
173
|
return { failedTasks, succeededTasks };
|
|
171
174
|
});
|
|
172
175
|
}
|
|
176
|
+
publishJobStateField(jobId, fieldName, value) {
|
|
177
|
+
this.adminforth.websocket.publish(`/background-jobs-state-update/${jobId}/${encodeStateFieldName(fieldName)}`, {
|
|
178
|
+
jobId,
|
|
179
|
+
fieldName,
|
|
180
|
+
value,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
publishTaskStateFields(jobId, taskIndex, state) {
|
|
184
|
+
for (const [fieldName, value] of Object.entries(state)) {
|
|
185
|
+
this.adminforth.websocket.publish(`/background-jobs-task-state-update/${jobId}/${encodeStateFieldName(fieldName)}`, {
|
|
186
|
+
jobId,
|
|
187
|
+
taskIndex,
|
|
188
|
+
fieldName,
|
|
189
|
+
value,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
173
193
|
triggerOnAllTasksDone(onAllTasksDone, levelDb, jobId) {
|
|
174
194
|
return __awaiter(this, void 0, void 0, function* () {
|
|
175
195
|
if (!onAllTasksDone) {
|
|
@@ -270,8 +290,8 @@ export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
|
270
290
|
}
|
|
271
291
|
//define the setTaskStateField and getTaskStateField functions to pass to the task
|
|
272
292
|
const setTaskStateField = (state) => __awaiter(this, void 0, void 0, function* () {
|
|
273
|
-
this.adminforth.websocket.publish(`/background-jobs-task-update/${jobId}`, { taskIndex, state });
|
|
274
293
|
yield this.setLevelDbTaskStateField(jobLevelDb, taskIndex.toString(), state);
|
|
294
|
+
this.publishTaskStateFields(jobId, taskIndex, state);
|
|
275
295
|
});
|
|
276
296
|
const getTaskStateField = () => __awaiter(this, void 0, void 0, function* () {
|
|
277
297
|
return yield this.getLevelDbTaskStateField(jobLevelDb, taskIndex.toString());
|
|
@@ -397,10 +417,10 @@ export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
|
397
417
|
const state = jobRecord[this.options.stateField];
|
|
398
418
|
const parsedState = JSON.parse(state);
|
|
399
419
|
parsedState[key] = value;
|
|
400
|
-
this.adminforth.websocket.publish(`/background-jobs`, { jobId, state: parsedState });
|
|
401
420
|
yield this.adminforth.resource(this.getResourceId()).update(jobId, {
|
|
402
421
|
[this.options.stateField]: JSON.stringify(parsedState),
|
|
403
422
|
});
|
|
423
|
+
this.publishJobStateField(jobId, key, value);
|
|
404
424
|
});
|
|
405
425
|
}
|
|
406
426
|
getJobField(jobId, key) {
|
package/index.ts
CHANGED
|
@@ -21,6 +21,10 @@ type taskType = {
|
|
|
21
21
|
skip?: boolean;
|
|
22
22
|
state: Record<string, any>;
|
|
23
23
|
}
|
|
24
|
+
|
|
25
|
+
function encodeStateFieldName(fieldName: string): string {
|
|
26
|
+
return encodeURIComponent(fieldName);
|
|
27
|
+
}
|
|
24
28
|
|
|
25
29
|
export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
26
30
|
options: PluginOptions;
|
|
@@ -184,6 +188,25 @@ export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
|
184
188
|
return { failedTasks, succeededTasks };
|
|
185
189
|
}
|
|
186
190
|
|
|
191
|
+
private publishJobStateField(jobId: string, fieldName: string, value: any) {
|
|
192
|
+
this.adminforth.websocket.publish(`/background-jobs-state-update/${jobId}/${encodeStateFieldName(fieldName)}`, {
|
|
193
|
+
jobId,
|
|
194
|
+
fieldName,
|
|
195
|
+
value,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private publishTaskStateFields(jobId: string, taskIndex: number, state: Record<string, any>) {
|
|
200
|
+
for (const [fieldName, value] of Object.entries(state)) {
|
|
201
|
+
this.adminforth.websocket.publish(`/background-jobs-task-state-update/${jobId}/${encodeStateFieldName(fieldName)}`, {
|
|
202
|
+
jobId,
|
|
203
|
+
taskIndex,
|
|
204
|
+
fieldName,
|
|
205
|
+
value,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
187
210
|
private async triggerOnAllTasksDone(onAllTasksDone: onAllTasksDoneType | undefined, levelDb: Level, jobId: string) {
|
|
188
211
|
if (!onAllTasksDone) {
|
|
189
212
|
return;
|
|
@@ -306,8 +329,8 @@ export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
|
306
329
|
|
|
307
330
|
//define the setTaskStateField and getTaskStateField functions to pass to the task
|
|
308
331
|
const setTaskStateField = async (state: Record<string, any>) => {
|
|
309
|
-
this.adminforth.websocket.publish(`/background-jobs-task-update/${jobId}`, { taskIndex, state });
|
|
310
332
|
await this.setLevelDbTaskStateField(jobLevelDb, taskIndex.toString(), state);
|
|
333
|
+
this.publishTaskStateFields(jobId, taskIndex, state);
|
|
311
334
|
}
|
|
312
335
|
const getTaskStateField = async () => {
|
|
313
336
|
return await this.getLevelDbTaskStateField(jobLevelDb, taskIndex.toString());
|
|
@@ -435,10 +458,10 @@ export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
|
435
458
|
const state = jobRecord[this.options.stateField];
|
|
436
459
|
const parsedState = JSON.parse(state);
|
|
437
460
|
parsedState[key] = value;
|
|
438
|
-
this.adminforth.websocket.publish(`/background-jobs`, { jobId, state: parsedState });
|
|
439
461
|
await this.adminforth.resource(this.getResourceId()).update(jobId, {
|
|
440
462
|
[this.options.stateField]: JSON.stringify(parsedState),
|
|
441
463
|
});
|
|
464
|
+
this.publishJobStateField(jobId, key, value);
|
|
442
465
|
}
|
|
443
466
|
|
|
444
467
|
public async getJobField(jobId: string, key: string) {
|
|
@@ -629,4 +652,4 @@ export default class BackgroundJobsPlugin extends AdminForthPlugin {
|
|
|
629
652
|
});
|
|
630
653
|
}
|
|
631
654
|
|
|
632
|
-
}
|
|
655
|
+
}
|