Skip to content

Commit

Permalink
Convert RecordSet.remove to requestRemoval thunk. Paginate delete, ma…
Browse files Browse the repository at this point in the history
…ke transactional
  • Loading branch information
LocalNewsTV committed Jan 2, 2025
1 parent a2a2750 commit e3aaadb
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 26 deletions.
8 changes: 2 additions & 6 deletions app/src/UI/Overlay/Records/Records.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@ import { OverlayHeader } from '../OverlayHeader';
import { useHistory } from 'react-router-dom';
import { useDispatch, useSelector } from 'utils/use_selector';
import UserSettings from 'state/actions/userSettings/UserSettings';
import { RecordSetType, UserRecordCacheStatus } from 'interfaces/UserRecordSet';
import { RecordSetType } from 'interfaces/UserRecordSet';
import Prompt from 'state/actions/prompts/Prompt';
import RecordSetDetails from './RecordSetDetails';
import RecordSetControl from './RecordSetControl';
import { MOBILE } from 'state/build-time-config';
import filterRecordsetsByNetworkState from 'utils/filterRecordsetsByNetworkState';
import RecordCache from 'state/actions/cache/RecordCache';

export const Records = () => {
const DEFAULT_RECORD_TYPES = ['All InvasivesBC Activities', 'All IAPP Records', 'My Drafts'];
Expand Down Expand Up @@ -50,10 +49,7 @@ export const Records = () => {
e.stopPropagation();
const callback = (userConfirmation: boolean) => {
if (userConfirmation) {
if (recordSets[set]?.cacheMetadata?.status === UserRecordCacheStatus.CACHED) {
dispatch(RecordCache.deleteCache({ setId: set }));
}
setTimeout(() => dispatch(UserSettings.RecordSet.remove(set)), 250);
dispatch(UserSettings.RecordSet.requestRemoval({ setId: set }));
}
};
dispatch(
Expand Down
18 changes: 18 additions & 0 deletions app/src/state/actions/userSettings/RecordSet.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { createAction, createAsyncThunk, nanoid } from '@reduxjs/toolkit';
import { RECORD_COLOURS } from 'constants/colors';
import { RecordSetType, UserRecordCacheStatus, UserRecordSet } from 'interfaces/UserRecordSet';
import { MOBILE } from 'state/build-time-config';
import { RootState } from 'state/reducers/rootReducer';
import { RecordCacheServiceFactory } from 'utils/record-cache/context';
import RecordCache from '../cache/RecordCache';

export interface IUpdateFilter {
setID: string | number;
Expand Down Expand Up @@ -56,6 +59,21 @@ class RecordSet {
}
);

static readonly requestRemoval = createAsyncThunk(
`${this.PREFIX}/requestRemoval`,
async (spec: { setId: string }, thunkAPI) => {
const state = thunkAPI.getState() as RootState;
const { recordSets } = state.UserSettings;
if (MOBILE && recordSets[spec.setId].cacheMetadata.status == UserRecordCacheStatus.CACHED) {
const deletionResult = await thunkAPI.dispatch(RecordCache.deleteCache(spec));
if (RecordCache.deleteCache.rejected.match(deletionResult)) {
throw Error('Cache failed to delete');
}
}
return spec.setId;
}
);

static readonly updateFilter = createAction<IUpdateFilter>(`${this.PREFIX}/updateFilter`);
static readonly removeFilter = createAction<IRemoveFilter>(`${this.PREFIX}/removeFilter`);

Expand Down
15 changes: 1 addition & 14 deletions app/src/state/reducers/userSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ function createUserSettingsReducer(configuration: AppConfig): (UserSettingsState
draftState.mapCenter = action.payload as [number, number];
} else if (UserSettings.RecordSet.add.match(action)) {
draftState.recordSets[Date.now().toString()] ??= action.payload;
} else if (UserSettings.RecordSet.remove.match(action)) {
} else if (UserSettings.RecordSet.requestRemoval.fulfilled.match(action)) {
delete draftState.recordSets[action.payload];
} else if (UserSettings.RecordSet.set.match(action)) {
Object.keys(action.payload.updatedSet).forEach((key) => {
Expand Down Expand Up @@ -218,19 +218,6 @@ function createUserSettingsReducer(configuration: AppConfig): (UserSettingsState
draftState.recordSets[action.meta.arg.setId].cacheMetadata = {
status: UserRecordCacheStatus.NOT_CACHED
};
} else if (UserSettings.RecordSet.syncCacheStatusWithCacheService.fulfilled.match(action)) {
const cacheStatus = action.payload;
for (const cachedSet of cacheStatus) {
if (draftState.recordSets[cachedSet.setId]) {
const { idList, cachedGeoJson, cachedCentroid } = draftState.recordSets[cachedSet.setId].cacheMetadata;
draftState.recordSets[cachedSet.setId].cacheMetadata = {
status: UserRecordCacheStatus.CACHED,
idList,
cachedGeoJson,
cachedCentroid
};
}
}
} else if (Activity.deleteSuccess.match(action)) {
draftState.activeActivity = null;
draftState.activeActivityDescription = null;
Expand Down
25 changes: 19 additions & 6 deletions app/src/utils/record-cache/sqlite-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,17 +287,30 @@ class SQLiteRecordCacheService extends RecordCacheService {
if (this.cacheDB == null) {
throw new Error(CACHE_UNAVAILABLE);
}

const RecordsToTable = {
[RecordSetType.Activity]: 'CACHED_RECORDS',
[RecordSetType.IAPP]: 'CACHED_IAPP_RECORDS'
};
const RECORD_TABLE = RecordsToTable[recordSetType];
await this.cacheDB.query(
// language=SQLite
`DELETE FROM ${RECORD_TABLE}
WHERE ID IN (${idsToDelete.map(() => '?').join(', ')})`,
[...idsToDelete]
);
const BATCH_AMOUNT = 100;

this.cacheDB.beginTransaction();
try {
for (let i = 0; i < idsToDelete.length; i += BATCH_AMOUNT) {
const sliced = idsToDelete.slice(i, Math.min(i + BATCH_AMOUNT, idsToDelete.length));
await this.cacheDB.query(
// language=SQLite
`DELETE FROM ${RECORD_TABLE}
WHERE ID IN (${sliced.map(() => '?').join(', ')})`,
[...sliced]
);
}
this.cacheDB.commitTransaction();
} catch (e) {
this.cacheDB.rollbackTransaction();
throw e;
}
}
private async initializeRecordCache(sqlite: SQLiteConnection) {
// Hold Migrations as named variable so we can use length to update the Db version automagically
Expand Down

0 comments on commit e3aaadb

Please sign in to comment.