Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Localize change sync operations #4070

Merged
merged 21 commits into from
May 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
b53ecc9
Add more sentry logging for sync errors.
rtibbles Apr 28, 2023
d6ab54c
Catch the entire syncChanges function.
rtibbles May 4, 2023
abeabb7
Update put method to add method to make creates explicit.
rtibbles May 7, 2023
c89ba35
Add Change classes to encapsulate and handle setting changes on the c…
rtibbles May 8, 2023
7feb5bf
Update syncChanges logic to handle queueing per tab.
rtibbles May 10, 2023
454bb23
Update forceServerSync to still attempt to sync all unsynced changes.
rtibbles May 10, 2023
fdded78
Link up change objects to the resource layer.
rtibbles May 10, 2023
3dd6ca3
Remove use of leader election. Do background polling only when docume…
rtibbles May 10, 2023
cd49812
Use serviceWorker during development.
rtibbles May 10, 2023
ce0bf14
Prevent circular dependencies. Use reactive watch to trigger queueing.
rtibbles May 10, 2023
6de69b9
Change updatedChanges to handle an object of changes, not the changed…
rtibbles May 10, 2023
e85491a
Include CHANGES_TABLE in transaction.
rtibbles May 10, 2023
8ec4840
Properly handle channel_id and user_id setting on changes.
rtibbles May 12, 2023
a73100b
Ensure key is not null.
rtibbles May 25, 2023
17ec8ff
Make the service worker serving handle no webpack devserver in debug …
rtibbles May 25, 2023
533b293
Make resolve/reject stack more comprehensible.
rtibbles May 25, 2023
58c09a6
Add in saving of the source to the change object.
rtibbles May 25, 2023
f64e6de
Update change tracker to only track changes from this client/tab.
rtibbles May 25, 2023
c0e34e4
Remove use of IGNORED_SOURCE as we are no longer syncing change events
rtibbles May 25, 2023
78e32c3
Update assessment item handling for change updates.
rtibbles May 30, 2023
05fccf0
Fix issues with copying.
rtibbles May 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,20 @@ export function addAssessmentItem(context, assessmentItem) {
hints: JSON.stringify(assessmentItem.hints || []),
};

return db.transaction('rw', [TABLE_NAMES.CONTENTNODE, TABLE_NAMES.ASSESSMENTITEM], () => {
return AssessmentItem.put(stringifiedAssessmentItem).then(([contentnode, assessment_id]) => {
context.commit('UPDATE_ASSESSMENTITEM', {
...assessmentItem,
contentnode,
assessment_id,
return db.transaction(
'rw',
[TABLE_NAMES.CONTENTNODE, TABLE_NAMES.ASSESSMENTITEM, TABLE_NAMES.CHANGES_TABLE],
() => {
return AssessmentItem.add(stringifiedAssessmentItem).then(([contentnode, assessment_id]) => {
context.commit('UPDATE_ASSESSMENTITEM', {
...assessmentItem,
contentnode,
assessment_id,
});
return updateNodeComplete(contentnode, context);
});
return updateNodeComplete(contentnode, context);
});
});
}
);
}
export function updateAssessmentItem(context, assessmentItem) {
return updateAssessmentItems(context, [assessmentItem]);
Expand All @@ -65,38 +69,46 @@ export function updateAssessmentItems(context, assessmentItems) {
context.commit('UPDATE_ASSESSMENTITEM', assessmentItem);
});

return db.transaction('rw', [TABLE_NAMES.CONTENTNODE, TABLE_NAMES.ASSESSMENTITEM], () => {
return Promise.all(
assessmentItems.map(assessmentItem => {
// API accepts answers and hints as strings
const stringifiedAssessmentItem = {
...assessmentItem,
};
if (assessmentItem.answers) {
stringifiedAssessmentItem.answers = JSON.stringify(assessmentItem.answers);
}
if (assessmentItem.hints) {
stringifiedAssessmentItem.hints = JSON.stringify(assessmentItem.hints);
}
return AssessmentItem.update(
[assessmentItem.contentnode, assessmentItem.assessment_id],
stringifiedAssessmentItem
).then(() => {
updateNodeComplete(assessmentItem.contentnode, context);
});
})
);
});
return db.transaction(
'rw',
[TABLE_NAMES.CONTENTNODE, TABLE_NAMES.ASSESSMENTITEM, TABLE_NAMES.CHANGES_TABLE],
() => {
return Promise.all(
assessmentItems.map(assessmentItem => {
// API accepts answers and hints as strings
const stringifiedAssessmentItem = {
...assessmentItem,
};
if (assessmentItem.answers) {
stringifiedAssessmentItem.answers = JSON.stringify(assessmentItem.answers);
}
if (assessmentItem.hints) {
stringifiedAssessmentItem.hints = JSON.stringify(assessmentItem.hints);
}
return AssessmentItem.update(
[assessmentItem.contentnode, assessmentItem.assessment_id],
stringifiedAssessmentItem
).then(() => {
updateNodeComplete(assessmentItem.contentnode, context);
});
})
);
}
);
}

export function deleteAssessmentItem(context, assessmentItem) {
return db.transaction('rw', [TABLE_NAMES.CONTENTNODE, TABLE_NAMES.ASSESSMENTITEM], () => {
return AssessmentItem.delete([assessmentItem.contentnode, assessmentItem.assessment_id]).then(
() => {
context.commit('DELETE_ASSESSMENTITEM', assessmentItem);
const contentnode = assessmentItem.contentnode;
return updateNodeComplete(contentnode, context);
}
);
});
return db.transaction(
'rw',
[TABLE_NAMES.CONTENTNODE, TABLE_NAMES.ASSESSMENTITEM, TABLE_NAMES.CHANGES_TABLE],
() => {
return AssessmentItem.delete([assessmentItem.contentnode, assessmentItem.assessment_id]).then(
() => {
context.commit('DELETE_ASSESSMENTITEM', assessmentItem);
const contentnode = assessmentItem.contentnode;
return updateNodeComplete(contentnode, context);
}
);
}
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import assessmentItem from '../../assessmentItem/index';
import file from 'shared/vuex/file';
import { ContentNode } from 'shared/data/resources';
import storeFactory from 'shared/vuex/baseStore';
import { mockChannelScope, resetMockChannelScope } from 'shared/utils/testing';

jest.mock('../../currentChannel/index');

Expand All @@ -15,8 +16,9 @@ describe('contentNode actions', () => {
let store;
let id;
const contentNodeDatum = { title: 'test', parent: parentId, lft: 1, tags: {} };
beforeEach(() => {
return ContentNode._put(contentNodeDatum).then(newId => {
beforeEach(async () => {
await mockChannelScope('test-123');
return ContentNode._add(contentNodeDatum).then(newId => {
id = newId;
contentNodeDatum.id = newId;
jest
Expand All @@ -25,7 +27,7 @@ describe('contentNode actions', () => {
jest
.spyOn(ContentNode, 'fetchModel')
.mockImplementation(() => Promise.resolve(contentNodeDatum));
return ContentNode._put({ title: 'notatest', parent: newId, lft: 2 }).then(() => {
return ContentNode._add({ title: 'notatest', parent: newId, lft: 2 }).then(() => {
store = storeFactory({
modules: {
assessmentItem,
Expand All @@ -38,7 +40,8 @@ describe('contentNode actions', () => {
});
});
});
afterEach(() => {
afterEach(async () => {
await resetMockChannelScope();
jest.restoreAllMocks();
return ContentNode.table.toCollection().delete();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export function createContentNode(context, { parent, kind, ...payload }) {
assessmentItems: [],
files: [],
});
return ContentNode.put(contentNodeData).then(id => {
return ContentNode.add(contentNodeData).then(id => {
context.commit('ADD_CONTENTNODE', {
id,
...contentNodeData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export function createSearch({ commit, rootState }, params) {
saved_by: rootState.session.currentUser.id,
created: new Date(),
};
return SavedSearch.put(data).then(id => {
return SavedSearch.add(data).then(id => {
commit('UPDATE_SAVEDSEARCH', {
id,
...data,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import channelList from '../index';
import { Channel, Invitation } from 'shared/data/resources';
import storeFactory from 'shared/vuex/baseStore';

jest.mock('shared/client');
jest.mock('shared/vuex/connectionPlugin');

const channel_id = '11111111111111111111111111111111';
Expand All @@ -18,7 +17,7 @@ describe('invitation actions', () => {
let store;
let id;
beforeEach(() => {
return Invitation.put(invitation).then(newId => {
return Invitation.add(invitation).then(newId => {
id = newId;
store = storeFactory({
modules: {
Expand Down Expand Up @@ -59,7 +58,7 @@ describe('invitation actions', () => {
// const channel = { id: channel_id, name: 'test', deleted: false, edit: true };
// beforeEach(() => {
// store.commit('channelList/SET_INVITATION_LIST', [{ id, ...invitation }]);
// return Channel.put(channel);
// return Channel.add(channel);
// });
// afterEach(() => {
// return Channel.table.toCollection().delete();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import channelSet from '../index';
import { ChannelSet } from 'shared/data/resources';
import { ChannelSet, injectVuexStore } from 'shared/data/resources';
import storeFactory from 'shared/vuex/baseStore';

jest.mock('shared/vuex/connectionPlugin');
Expand All @@ -14,17 +14,19 @@ describe('channelSet actions', () => {
edit: true,
};
beforeEach(() => {
return ChannelSet.put(channelSetDatum).then(newId => {
store = storeFactory({
modules: {
channelSet,
},
});
store.state.session.currentUser.id = userId;
injectVuexStore(store);
return ChannelSet.add(channelSetDatum).then(newId => {
id = newId;
store = storeFactory({
modules: {
channelSet,
},
});
store.state.session.currentUser.id = userId;
});
});
afterEach(() => {
injectVuexStore();
return ChannelSet.table.toCollection().delete();
});
describe('loadChannelSetList action', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ describe('startApp', () => {

describe('if there is a current user saved in a session', () => {
beforeEach(async () => {
await Session.put({ ...USER_1, CURRENT_USER });
await Session.table.put({ ...USER_1, CURRENT_USER });

const sessionTable = await Session.table.toArray();
expect(sessionTable).toEqual([{ ...USER_1, CURRENT_USER }]);
Expand Down Expand Up @@ -77,7 +77,7 @@ describe('startApp', () => {

describe('if there is the same current user saved in a session', () => {
beforeEach(async () => {
await Session.put({ ...USER_1, CURRENT_USER });
await Session.table.put({ ...USER_1, CURRENT_USER });

const sessionTable = await Session.table.toArray();
expect(sessionTable).toEqual([{ ...USER_1, CURRENT_USER }]);
Expand All @@ -91,7 +91,7 @@ describe('startApp', () => {

describe('if there is a different current user saved in a session', () => {
beforeEach(async () => {
await Session.put({ ...USER_2, CURRENT_USER });
await Session.table.put({ ...USER_2, CURRENT_USER });

const sessionTable = await Session.table.toArray();
expect(sessionTable).toEqual([{ ...USER_2, CURRENT_USER }]);
Expand Down
2 changes: 1 addition & 1 deletion contentcuration/contentcuration/frontend/shared/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ Vue.component('Menu', Menu);
function initiateServiceWorker() {
// Second conditional must be removed if you are doing dev work on the service
// worker.
if ('serviceWorker' in navigator && process.env.NODE_ENV === 'production') {
if ('serviceWorker' in navigator) {
const wb = new Workbox(window.Urls.service_worker());
let registration;

Expand Down
Loading