Skip to content

Commit 7a5e94b

Browse files
committed
Persist provenance as separate assets
1 parent 6669629 commit 7a5e94b

3 files changed

Lines changed: 73 additions & 10 deletions

File tree

src/storage/engines/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,12 +1453,24 @@ export abstract class StorageEngine {
14531453
return this.parseProvenanceStorageObject(provenanceObject);
14541454
}
14551455

1456+
async deleteProvenance(taskName: string) {
1457+
if (!this.currentParticipantId || !this.studyId) {
1458+
return;
1459+
}
1460+
try {
1461+
await this._deleteFromStorage(`provenance/${this.currentParticipantId}`, taskName);
1462+
} catch (error) {
1463+
console.warn(`Failed to delete provenance for task ${taskName}:`, error);
1464+
}
1465+
}
1466+
14561467
async saveProvenance(
14571468
provenanceGraph: StoredProvenance | null | undefined,
14581469
taskName: string,
14591470
) {
14601471
const provenanceToSave = normalizeStoredProvenance(provenanceGraph);
14611472
if (!provenanceToSave) {
1473+
await this.deleteProvenance(taskName);
14621474
return undefined;
14631475
}
14641476

src/storage/tests/highLevel.spec.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,49 @@ describe.each([
840840
});
841841
});
842842

843+
test('saveProvenance with null/undefined deletes existing provenance asset', async () => {
844+
storageEngine = new LocalStorageEngine(true);
845+
await storageEngine.connect();
846+
await storageEngine.initializeStudyDb(studyId);
847+
sequenceArray = await generateSequenceArray(configSimple);
848+
const participantSession = await storageEngine.initializeParticipantSession({}, configSimple, participantMetadata);
849+
const identifier = 'intro_0';
850+
851+
// First, save a provenance asset
852+
const provenanceGraph = {
853+
root: 'root',
854+
nodes: {
855+
root: {
856+
id: 'root',
857+
createdOn: 10,
858+
children: [],
859+
},
860+
},
861+
};
862+
await storageEngine.saveProvenance({
863+
aboveStimulus: undefined,
864+
belowStimulus: undefined,
865+
sidebar: undefined,
866+
stimulus: provenanceGraph,
867+
}, identifier);
868+
869+
// Verify it was saved
870+
let storedProvenance = await storageEngine.getProvenance(identifier, participantSession.participantId);
871+
expect(storedProvenance).toEqual({
872+
aboveStimulus: undefined,
873+
belowStimulus: undefined,
874+
sidebar: undefined,
875+
stimulus: provenanceGraph,
876+
});
877+
878+
// Now save with null — should delete the existing asset
879+
await storageEngine.saveProvenance(null, identifier);
880+
881+
// Verify it was deleted
882+
storedProvenance = await storageEngine.getProvenance(identifier, participantSession.participantId);
883+
expect(storedProvenance).toBeNull();
884+
});
885+
843886
test('saveAnswers coalesces to the latest answer and finalizeParticipant persists completion after delayed writes', async () => {
844887
storageEngine = new DelayedLocalStorageEngine(true);
845888
await storageEngine.connect();

src/store/hooks/useNextStep.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,26 @@ export function useNextStep() {
9090
timedOut: !collectData,
9191
};
9292
const answersToPersist = { ...answers, [identifier]: toSave };
93-
const handleResponsePersistenceError = (error: unknown) => {
94-
console.error('Failed to save participant response data', error);
95-
showNotification({
96-
title: 'Failed to Save Response',
97-
message: 'Your response could not be saved. Please check your connection and try again.',
98-
color: 'red',
99-
});
100-
};
10193

10294
if (storageEngine) {
103-
storageEngine.saveAnswers(answersToPersist).catch(handleResponsePersistenceError);
104-
storageEngine.saveProvenance(provenanceGraph, identifier).catch(handleResponsePersistenceError);
95+
storageEngine.saveAnswers(answersToPersist).catch((error) => {
96+
console.error('Failed to save participant response data', error);
97+
showNotification({
98+
title: 'Failed to Save Response',
99+
message: 'Your response could not be saved. Please check your connection and try again.',
100+
color: 'red',
101+
});
102+
});
103+
if (provenanceGraph) {
104+
storageEngine.saveProvenance(provenanceGraph, identifier).catch((error) => {
105+
console.error('Failed to save participant response data', error);
106+
showNotification({
107+
title: 'Failed to Save Response',
108+
message: 'Your response could not be saved. Please check your connection and try again.',
109+
color: 'red',
110+
});
111+
});
112+
}
105113
}
106114

107115
storeDispatch(

0 commit comments

Comments
 (0)