@@ -190,7 +190,7 @@ The plugin saves tasks and keeps executing them even after a server restart, so
190190 // diff-add
191191 // handler function
192192 // diff-add
193- handler : async ({ setTaskStateField , getTaskStateField }) => {
193+ handler : async ({ jobId , setTaskStateField , getTaskStateField }) => {
194194 // diff-add
195195 const state = await getTaskStateField ();
196196 // diff-add
@@ -245,7 +245,7 @@ After registering a handler, you can create a job. For example:
245245 // diff-add
246246 }
247247 // diff-add
248- backgroundJobsPlugin .startNewJob (
248+ const jobId = await backgroundJobsPlugin .startNewJob (
249249 // diff-add
250250 ' Example Job' , // job name
251251 // diff-add
@@ -316,6 +316,7 @@ const props = defineProps<{
316316 status: ' IN_PROGRESS' | ' DONE' | ' DONE_WITH_ERRORS' | ' CANCELLED' ;
317317 progress: number ; // 0 to 100
318318 createdAt: Date ;
319+ finishedAt: Date ;
319320 customComponent? : AdminForthComponentDeclarationFull ;
320321 };
321322}>();
@@ -426,5 +427,64 @@ Finally, register this component alongside the job task handler:
426427 })
427428
428429
430+ ` ` `
431+
432+
433+ ## Frontend API
434+ ### Job info popup
435+ If you want to imedeatelly open job info popup, you shoul return job id from you API, that creates job:
436+
437+ For example:
438+
439+ ` ` ` ts
440+ ...
441+
442+ const res = await callAdminForthApi ({
443+ path: ` /plugin/${props .meta .pluginInstanceId }/translate-selected-to-languages ` ,
444+ method: ' POST' ,
445+ body: {
446+ selectedIds: listOfIds ,
447+ selectedLanguages: Object .keys (checkedLanguages .value ).filter (lang => checkedLanguages .value [lang ]),
448+ },
449+ silentError: true ,
450+ });
451+
452+ if (res .ok ) {
453+ const jobId = res .jobId ;
454+ if (jobId ) {
455+ // diff-add
456+ window .OpenJobInfoPopup (jobId );
457+ }
458+ }
429459
430460` ` `
461+
462+ ## Backend api
463+
464+ Pluging provides some handy methods, that can be used in different situations:
465+
466+ ` ` ` ts
467+ // set key:value to the job state in the DB
468+ setJobField (jobId : string , key : string , value : any )
469+ // get job field from the state in db
470+ getJobField (jobId : string , key : string )
471+ // get job state from the db
472+ getJobState (jobId : string )
473+ /**
474+ *
475+ * executes code atomically, if you have many task, that can update task state,
476+ * better use this method to avoid cases, when in the task state writes invalid data.
477+ *
478+ **/
479+ updateJobFieldsAtomically (jobId : string , updateFunction : () => Promise < void > )
480+
481+ // for example
482+ backgroundJobsPlugin .updateJobFieldsAtomically (jobId , async () => {
483+ // do all set / get fields in this function to make state update atomic and there is no conflicts when 2 tasks in parallel do get before set.
484+ // don't do long awaits in this callback, since it has exclusive lock.
485+ let totalUsedTokens = await backgroundJobsPlugin .getJobField (jobId , ' totalUsedTokens' );
486+ totalUsedTokens += promptCost ;
487+ await backgroundJobsPlugin .setJobField (jobId , ' totalUsedTokens' , totalUsedTokens );
488+ })
489+
490+ ` ` `
0 commit comments