Skip to content

Commit

Permalink
Create snapshots on transitions
Browse files Browse the repository at this point in the history
  • Loading branch information
FyreByrd committed Sep 18, 2024
1 parent b86ad72 commit e4755b2
Show file tree
Hide file tree
Showing 8 changed files with 184 additions and 86 deletions.
2 changes: 1 addition & 1 deletion source/SIL.AppBuilder.Portal/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ export * as BullMQ from './BullJobTypes.js';
export { scriptoriaQueue } from './bullmq.js';
export { default as DatabaseWrites } from './databaseProxy/index.js';
export { readonlyPrisma as prisma } from './prisma.js';
export { NoAdminS3 } from './workflow.js';
export { NoAdminS3, getSnapshot } from './workflow/index.js';
14 changes: 14 additions & 0 deletions source/SIL.AppBuilder.Portal/common/public/workflow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,20 @@ import type {
TransitionDefinition
} from 'xstate';

export type WorkflowContext = {
//later: narrow types if necessary
instructions: string;
includeFields: string[];
includeReviewers: boolean;
includeArtifacts: string | boolean;
start?: string;
productId: string;
};

export type WorkflowInput = {
productId?: string;
};

export type StateNode = {
id: number;
label: string;
Expand Down
40 changes: 40 additions & 0 deletions source/SIL.AppBuilder.Portal/common/workflow/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import DatabaseWrites from '../databaseProxy/index.js';
import { prisma } from '../index.js';
import { WorkflowContext } from '../public/workflow.js';
import { AnyStateMachine } from 'xstate';

export type Snapshot = {
value: string;
context: WorkflowContext;
};

export async function createSnapshot(state: string, context: WorkflowContext) {
return DatabaseWrites.workflowInstances.update({
where: {
ProductId: context.productId
},
data: {
Snapshot: JSON.stringify({ value: state, context: context } as Snapshot)
}
});
}

export async function getSnapshot(productId: string, machine: AnyStateMachine) {
const snap = JSON.parse(
(
await prisma.workflowInstances.findUnique({
where: {
ProductId: productId
},
select: {
Snapshot: true
}
})
)?.Snapshot || 'null'
) as Snapshot | undefined;

if (snap) {
return machine.resolveState(snap);
}
return undefined;
}
2 changes: 2 additions & 0 deletions source/SIL.AppBuilder.Portal/common/workflow/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { NoAdminS3 } from './no-admin-s3.js';
export { getSnapshot } from './db.js';
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import { setup, assign } from 'xstate';
import DatabaseWrites from './databaseProxy/index.js';
import DatabaseWrites from '../databaseProxy/index.js';
import { WorkflowContext, WorkflowInput } from '../public/workflow.js';
import { createSnapshot } from './db.js';
import { create } from 'domain';

//later: update snapshot on state exits (define a function to do it), store instance id in context
//later: update UserTasks on entry?
export const NoAdminS3 = setup({
types: {
context: {} as {
//later: narrow types if necessary
instructions: string;
includeFields: string[];
includeReviewers: boolean;
includeArtifacts: string | boolean;
start?: string;
productId: string;
},
input: {} as {
productId?: string;
}
context: {} as WorkflowContext,
input: {} as WorkflowInput
}
}).createMachine({
initial: 'Start',
Expand All @@ -42,7 +35,7 @@ export const NoAdminS3 = setup({
Snapshot: '',
ProductId: context.productId
}
})
});
},
always: [
{
Expand Down Expand Up @@ -74,8 +67,8 @@ export const NoAdminS3 = setup({
target: 'Product Build'
},
{
guard: ({ context }) => context.start === 'Verify And Publish',
target: 'Verify And Publish'
guard: ({ context }) => context.start === 'Verify and Publish',
target: 'Verify and Publish'
},
{
guard: ({ context }) => context.start === 'Publish Product',
Expand All @@ -99,7 +92,8 @@ export const NoAdminS3 = setup({
'Product Creation': {
entry: [
assign({ instructions: 'waiting' }),
() => {
({ context }) => {
createSnapshot('Product Creation', context);
//later: hook into build engine
console.log('Creating Product');
}
Expand All @@ -111,10 +105,15 @@ export const NoAdminS3 = setup({
}
},
'App Builder Configuration': {
entry: assign({
instructions: 'app_configuration',
includeFields: ['storeDescription', 'listingLanguageCode', 'projectURL']
}),
entry: [
assign({
instructions: 'app_configuration',
includeFields: ['storeDescription', 'listingLanguageCode', 'projectURL']
}),
({ context }) => {
createSnapshot('App Builder Configuration', context);
}
],
on: {
'Continue.Owner': {
target: 'Product Build'
Expand All @@ -126,10 +125,15 @@ export const NoAdminS3 = setup({
}
},
'Author Configuration': {
entry: assign({
instructions: 'app_configuration',
includeFields: ['storeDescription', 'listingLanguageCode', 'projectURL']
}),
entry: [
assign({
instructions: 'app_configuration',
includeFields: ['storeDescription', 'listingLanguageCode', 'projectURL']
}),
({ context }) => {
createSnapshot('Author Configuration', context);
}
],
on: {
'Continue.Author': {
target: 'App Builder Configuration'
Expand All @@ -140,10 +144,15 @@ export const NoAdminS3 = setup({
}
},
'Synchronize Data': {
entry: assign({
instructions: 'synchronize_data',
includeFields: ['storeDescription', 'listingLanguageCode']
}),
entry: [
assign({
instructions: 'synchronize_data',
includeFields: ['storeDescription', 'listingLanguageCode']
}),
({ context }) => {
createSnapshot('Synchronize Data', context);
}
],
on: {
'Continue.Owner': {
target: 'Product Build'
Expand All @@ -155,10 +164,15 @@ export const NoAdminS3 = setup({
}
},
'Author Download': {
entry: assign({
instructions: 'authors_download',
includeFields: ['storeDescription', 'listingLanguageCode', 'projectURL']
}),
entry: [
assign({
instructions: 'authors_download',
includeFields: ['storeDescription', 'listingLanguageCode', 'projectURL']
}),
({ context }) => {
createSnapshot('Author Download', context);
}
],
on: {
'Continue.Author': {
target: 'Author Upload'
Expand All @@ -169,10 +183,15 @@ export const NoAdminS3 = setup({
}
},
'Author Upload': {
entry: assign({
instructions: 'authors_upload',
includeFields: ['storeDescription', 'listingLanguageCode']
}),
entry: [
assign({
instructions: 'authors_upload',
includeFields: ['storeDescription', 'listingLanguageCode']
}),
({ context }) => {
createSnapshot('Author Upload', context);
}
],
on: {
'Continue.Author': {
target: 'Synchronize Data'
Expand All @@ -188,26 +207,34 @@ export const NoAdminS3 = setup({
assign({
instructions: 'waiting'
}),
({ context }) => {
createSnapshot('Product Build', context);
},
() => {
console.log('Building Product');
}
],
on: {
'Build Successful.Auto': {
target: 'Verify And Publish'
target: 'Verify and Publish'
},
'Build Failed.Auto': {
target: 'Synchronize Data'
}
}
},
'Verify And Publish': {
entry: assign({
instructions: 'verify_and_publish',
includeFields: ['storeDescription', 'listingLanguageCode', 'projectURL'],
includeReviewers: true,
includeArtifacts: true
}),
'Verify and Publish': {
entry: [
assign({
instructions: 'verify_and_publish',
includeFields: ['storeDescription', 'listingLanguageCode', 'projectURL'],
includeReviewers: true,
includeArtifacts: true
}),
({ context }) => {
createSnapshot('Verify and Publish', context);
}
],
exit: assign({
includeReviewers: false,
includeArtifacts: false
Expand All @@ -227,18 +254,26 @@ export const NoAdminS3 = setup({
},
'Email Reviewers': {
//later: connect to backend to email reviewers
entry: () => {
console.log('Emailing Reviewers');
},
entry: [
() => {
console.log('Emailing Reviewers');
},
({ context }) => {
createSnapshot('Email Reviewers', context);
}
],
on: {
'Default.Auto': {
target: 'Verify And Publish'
target: 'Verify and Publish'
}
}
},
'Publish Product': {
entry: [
assign({ instructions: 'waiting' }),
({ context }) => {
createSnapshot('Publish Product', context);
},
() => {
console.log('Publishing Product');
}
Expand All @@ -253,18 +288,25 @@ export const NoAdminS3 = setup({
}
},
Published: {
entry: assign({
instructions: '',
includeFields: ['storeDescription', 'listingLanguageCode']
}),
entry: [
assign({
instructions: '',
includeFields: ['storeDescription', 'listingLanguageCode']
}),
({ context }) => {
createSnapshot('Published', context);
}
],
type: 'final'
}
},
on: {
jump: {
actions: assign({
start: ({ event }) => event.target
}),
'Jump To': {
actions: [
assign({
start: ({ event }) => event.target
})
],
target: '.Start'
}
}
Expand Down
Loading

0 comments on commit e4755b2

Please sign in to comment.