Skip to content

Commit

Permalink
Standardize Function names, implement BaseCacheService, strengthen ty…
Browse files Browse the repository at this point in the history
…ping
  • Loading branch information
LocalNewsTV committed Jan 16, 2025
1 parent 95655a3 commit 3bdab17
Show file tree
Hide file tree
Showing 14 changed files with 123 additions and 96 deletions.
12 changes: 6 additions & 6 deletions app/src/UI/LegacyMap/helpers/recordset-layers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ export const createOfflineIappLayer = async (map: maplibregl.Map, layer: any) =>
return;
}
const service = await RecordCacheServiceFactory.getPlatformInstance();
const repo = await service.fetchRepository(layer.recordSetID);
const repo = await service.getRepository(layer.recordSetID);

if (!repo.cachedGeoJson) {
if (!repo?.cachedGeoJson) {
return;
}
const layerID = formatLayerID(layer.recordSetID, layer.tableFiltersHash);
Expand Down Expand Up @@ -192,9 +192,9 @@ export const createOfflineActivityLayer = async (map: maplibregl.Map, layer: any
return;
}
const service = await RecordCacheServiceFactory.getPlatformInstance();
const { cachedCentroid, cachedGeoJson } = await service.fetchRepository(layer.recordSetID);
const metadata = await service.getRepository(layer.recordSetID);

if (!cachedCentroid || !cachedGeoJson) {
if (!metadata?.cachedCentroid || !metadata?.cachedGeoJson) {
return;
}

Expand All @@ -203,8 +203,8 @@ export const createOfflineActivityLayer = async (map: maplibregl.Map, layer: any
const CENTROID_ID = `${GEOJSON_ID}-centroid`;
const color = getPaintBySchemeOrColor(layer);

const geoJsonSourceObj: GeoJSONSourceSpecification = cachedGeoJson;
const centroidSourceObj: GeoJSONSourceSpecification = cachedCentroid;
const geoJsonSourceObj: GeoJSONSourceSpecification = metadata.cachedGeoJson;
const centroidSourceObj: GeoJSONSourceSpecification = metadata.cachedCentroid;

const circleMarkerZoomedOutLayerCentroid: CircleLayerSpecification = getCircleMarkerZoomedOutLayer(CENTROID_ID, {
color,
Expand Down
2 changes: 1 addition & 1 deletion app/src/state/actions/cache/RecordCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class RecordCache {
const recordSet = state.UserSettings.recordSets[spec.setId];
const bbox = await getBoundingBoxFromRecordsetFilters(recordSet);

const downloadCompleted = await service.downloadCache({
const downloadCompleted = await service.download({
API_BASE: state.Configuration.current.API_BASE,
bbox,
idsToCache,
Expand Down
2 changes: 1 addition & 1 deletion app/src/state/sagas/activity/offline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export function* handle_ACTIVITY_GET_LOCAL_REQUEST(action: PayloadAction<string>
}
} else {
try {
const service: RecordCacheService = yield RecordCacheServiceFactory.getPlatformInstance();
const service = yield RecordCacheServiceFactory.getPlatformInstance();
const result = yield service.loadActivity(activityID);

const datav2 = {
Expand Down
2 changes: 1 addition & 1 deletion app/src/state/sagas/iappsite/dataAccess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function* handle_IAPP_GET_REQUEST(iappId: PayloadAction<string>) {
try {
const connected = yield select(selectNetworkConnected);
if (MOBILE && !connected) {
const service: RecordCacheService = yield RecordCacheServiceFactory.getPlatformInstance();
const service = yield RecordCacheServiceFactory.getPlatformInstance();
const result = yield service.loadIapp(iappId.payload, IappRecordMode.Record);
yield put(IappActions.getSuccess(result));
} else {
Expand Down
8 changes: 4 additions & 4 deletions app/src/state/sagas/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ import { RecordCacheServiceFactory } from 'utils/record-cache/context';
import bboxToPolygon from 'utils/bboxToPolygon';
import IappActions from 'state/actions/activity/Iapp';
import IappRecord from 'interfaces/IappRecord';
import { RecordCacheAddSpec } from 'utils/record-cache';
import { RepositoryMetadata } from 'utils/record-cache';
import NetworkActions from 'state/actions/network/NetworkActions';

function* handle_USER_SETTINGS_GET_INITIAL_STATE_SUCCESS(action) {
Expand Down Expand Up @@ -163,7 +163,7 @@ function* handle_WHATS_HERE_FEATURE(whatsHereFeature: PayloadAction<Feature>) {
const service = yield RecordCacheServiceFactory.getPlatformInstance();
const repos = yield service.listRepositories();

const recordSetsInBoundingBox = repos.filter((repo: RecordCacheAddSpec) => {
const recordSetsInBoundingBox = repos.filter((repo: RepositoryMetadata) => {
const { status, bbox } = repo;
return (
status === UserRecordCacheStatus.CACHED &&
Expand Down Expand Up @@ -223,7 +223,7 @@ function* handle_WHATS_HERE_IAPP_ROWS_REQUEST() {
let records: IappRecord[];
if (MOBILE && !connected) {
const service = yield RecordCacheServiceFactory.getPlatformInstance();
records = yield service.fetchPaginatedCachedIappRecords(
records = yield service.getPaginatedCachedIappRecords(
whatsHere.IAPPIDs.map((id) => id.toString()),
whatsHere.IAPPPage,
whatsHere.IAPPLimit
Expand Down Expand Up @@ -313,7 +313,7 @@ function* handle_WHATS_HERE_ACTIVITY_ROWS_REQUEST() {
let records: UserRecord[];
if (MOBILE && !connected) {
const service = yield RecordCacheServiceFactory.getPlatformInstance();
records = yield service.fetchPaginatedCachedRecords(
records = yield service.getPaginatedCachedActivityRecords(
whatsHere.ActivityIDs,
whatsHere.ActivityPage,
whatsHere.ActivityLimit
Expand Down
12 changes: 6 additions & 6 deletions app/src/state/sagas/map/dataAccess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export function* handle_ACTIVITIES_GET_IDS_FOR_RECORDSET_REQUEST(action) {
const recordSet = currentState.recordSets[action.payload.recordSetID] ?? null;
if (recordSet.cacheMetadataStatus === UserRecordCacheStatus.CACHED) {
const service = yield RecordCacheServiceFactory.getPlatformInstance();
const ids = yield service.fetchIdList(action.payload.recordSetID);
const ids = yield service.getIdList(action.payload.recordSetID);

yield put({
type: ACTIVITIES_GET_IDS_FOR_RECORDSET_SUCCESS,
Expand Down Expand Up @@ -160,7 +160,7 @@ export function* handle_IAPP_GET_IDS_FOR_RECORDSET_REQUEST(action) {
} else {
const service = yield RecordCacheServiceFactory.getPlatformInstance();
if (yield service.isCached(action.payload.recordSetID)) {
const ids = yield service.fetchIdList(action.payload.recordSetID);
const ids = yield service.getIdList(action.payload.recordSetID);
yield put({
type: IAPP_GET_IDS_FOR_RECORDSET_SUCCESS,
payload: {
Expand Down Expand Up @@ -237,8 +237,8 @@ export function* handle_ACTIVITIES_TABLE_ROWS_GET_REQUEST(action) {

if (userMobileOffline) {
const service = yield RecordCacheServiceFactory.getPlatformInstance();
const recordSetIdList = yield service.fetchIdList(recordSetID);
const records = yield service.fetchPaginatedCachedRecords(recordSetIdList, page, limit);
const recordSetIdList = yield service.getIdList(recordSetID);
const records = yield service.getPaginatedCachedActivityRecords(recordSetIdList, page, limit);
yield put(
Activity.getRowsSuccess({
recordSetID: recordSetID,
Expand Down Expand Up @@ -289,8 +289,8 @@ export function* handle_IAPP_TABLE_ROWS_GET_REQUEST(action: PayloadAction<IappTa
}
if (userMobileOffline) {
const service = yield RecordCacheServiceFactory.getPlatformInstance();
const recordSetIdList = yield service.fetchIdList(recordSetID) ?? [];
const records = yield service.fetchPaginatedCachedIappRecords(recordSetIdList, page, limit);
const recordSetIdList = yield service.getIdList(recordSetID.toString()) ?? [];
const records = yield service.getPaginatedCachedIappRecords(recordSetIdList, page, limit);
yield put(
IappActions.getRowsSuccess({
recordSetID: recordSetID,
Expand Down
3 changes: 2 additions & 1 deletion app/src/utils/record-cache/context.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Platform, PLATFORM } from 'state/build-time-config';
import { RecordCacheService } from 'utils/record-cache/index';
import { SQLiteRecordCacheService } from 'utils/record-cache/sqlite-cache';
import { LocalForageRecordCacheService } from 'utils/record-cache/localforage-cache';

class RecordCacheServiceFactory {
static async getPlatformInstance() {
static async getPlatformInstance(): Promise<RecordCacheService> {
if (PLATFORM == Platform.IOS) {
return SQLiteRecordCacheService.getInstance();
}
Expand Down
67 changes: 36 additions & 31 deletions app/src/utils/record-cache/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { RecordSetType, UserRecordCacheStatus } from 'interfaces/UserRecordSet';
import { GeoJSONSourceSpecification } from 'maplibre-gl';
import { getCurrentJWT } from 'state/sagas/auth/auth';
import { getSelectColumnsByRecordSetType } from 'state/sagas/map/dataAccess';
import BaseCacheService from 'utils/base-classes/BaseCacheService';
import { RepositoryBoundingBoxSpec } from 'utils/tile-cache';

export enum IappRecordMode {
Expand All @@ -25,7 +26,7 @@ export interface RecordCacheDownloadRequestSpec {
* @property { GeoJSONSourceSpecification } cachedCentroid Cached Points for high map layers
* @property { UserRecordCacheStatus } status Cache Status.
*/
export interface RecordCacheAddSpec {
export interface RepositoryMetadata {
setId: string;
cacheTime: Date;
cachedIds: string[];
Expand Down Expand Up @@ -58,53 +59,57 @@ export interface CacheDownloadSpec {
recordSetType: RecordSetType;
}

abstract class RecordCacheService {
abstract class RecordCacheService extends BaseCacheService<
RepositoryMetadata,
CacheDownloadSpec,
RecordCacheProgressCallbackParameters,
UserRecordCacheStatus
> {
private readonly RECORDS_BETWEEN_PROGRESS_UPDATES = 25;
protected constructor() {}

protected constructor() {
super();
}

static async getInstance(): Promise<RecordCacheService> {
throw new Error('unimplemented in abstract base class');
}
protected abstract addOrUpdateRepository(spec: RepositoryMetadata): Promise<void>;

abstract saveActivity(id: string, data: unknown): Promise<void>;
protected abstract deleteCachedRecordsFromIds(idsToDelete: string[], recordSetType: RecordSetType): Promise<void>;

abstract saveIapp(id: string, iappRecord: unknown, iappTableRow: unknown): Promise<void>;
/** */
public abstract loadActivity(id: string): Promise<unknown>;

abstract deleteCachedRecordsFromIds(idsToDelete: string[], recordSetType: RecordSetType): Promise<void>;
public abstract loadIapp(id: string, type: IappRecordMode): Promise<IappRecord | IappTableRow>;

abstract loadActivity(id: string): Promise<unknown>;
protected abstract saveActivity(id: string, data: unknown): Promise<void>;

abstract loadIapp(id: string, type: IappRecordMode): Promise<IappRecord | IappTableRow>;
protected abstract saveIapp(id: string, iappRecord: unknown, iappTableRow: unknown): Promise<void>;

abstract fetchPaginatedCachedIappRecords(
public abstract getPaginatedCachedActivityRecords(
recordSetIdList: string[],
page: number,
limit: number
): Promise<IappRecord[]>;

abstract fetchPaginatedCachedRecords(recordSetIdList: string[], page: number, limit: number): Promise<UserRecord[]>;

abstract addOrUpdateRepository(spec: RecordCacheAddSpec): Promise<void>;

abstract deleteRepository(repositoryId: string): Promise<void>;
): Promise<UserRecord[]>;

abstract fetchRepository(repositoryId: string): Promise<RecordCacheAddSpec>;

abstract isCached(repositoryId: string): Promise<boolean>;

abstract fetchIdList(repositoryId: string): Promise<string[]>;
public abstract getPaginatedCachedIappRecords(
recordSetIdList: string[],
page: number,
limit: number
): Promise<IappRecord[]>;

abstract listRepositories(): Promise<RecordCacheAddSpec[]>;
public abstract isCached(repositoryId: string): Promise<boolean>;

abstract loadIappRecordsetSourceMetadata(ids: string[]): Promise<RecordSetSourceMetadata>;
public abstract getIdList(repositoryId: string): Promise<string[]>;

abstract loadRecordsetSourceMetadata(ids: string[]): Promise<RecordSetSourceMetadata>;
protected abstract createIappRecordsetSourceMetadata(ids: string[]): Promise<RecordSetSourceMetadata>;

abstract setRepositoryStatus(repositoryId: string, status: UserRecordCacheStatus): Promise<void>;
protected abstract createActivityRecordsetSourceMetadata(ids: string[]): Promise<RecordSetSourceMetadata>;

abstract checkForAbort(id: string): Promise<boolean>;

async downloadCache(spec: CacheDownloadSpec): Promise<boolean> {
public async download(spec: CacheDownloadSpec): Promise<boolean> {
const args = {
idsToCache: spec.idsToCache,
setId: spec.setId,
Expand All @@ -127,9 +132,9 @@ abstract class RecordCacheService {

let downloadCompleted = true;
if (spec.recordSetType === RecordSetType.Activity && (await this.downloadActivity(args))) {
Object.assign(responseData, await this.loadRecordsetSourceMetadata(spec.idsToCache));
Object.assign(responseData, await this.createActivityRecordsetSourceMetadata(spec.idsToCache));
} else if (spec.recordSetType === RecordSetType.IAPP && (await this.downloadIapp(args))) {
Object.assign(responseData, await this.loadIappRecordsetSourceMetadata(spec.idsToCache));
Object.assign(responseData, await this.createIappRecordsetSourceMetadata(spec.idsToCache));
} else {
downloadCompleted = false;
this.deleteRepository(spec.setId);
Expand All @@ -153,7 +158,7 @@ abstract class RecordCacheService {
* Download Records for IAPP Given a list of IDs
* @returns { boolean } download was successful
*/
async downloadIapp(
private async downloadIapp(
spec: RecordCacheDownloadRequestSpec,
progressCallback?: (currentProgress: RecordCacheProgressCallbackParameters) => void
): Promise<boolean> {
Expand Down Expand Up @@ -203,7 +208,7 @@ abstract class RecordCacheService {
* Download Records for Activities Given a list of IDs
* @returns { boolean } download was successful
*/
async downloadActivity(
private async downloadActivity(
spec: RecordCacheDownloadRequestSpec,
progressCallback?: (currentProgress: RecordCacheProgressCallbackParameters) => void
): Promise<boolean> {
Expand All @@ -224,7 +229,7 @@ abstract class RecordCacheService {
}
return !abort;
}
async stopDownload(repositoryId: string): Promise<void> {
public async stopDownload(repositoryId: string): Promise<void> {
const repositories = await this.listRepositories();
const foundIndex = repositories.findIndex((repo) => repo.setId === repositoryId);
if (foundIndex === -1) throw Error(`Repository ${repositoryId} wasn't found`);
Expand Down
29 changes: 17 additions & 12 deletions app/src/utils/record-cache/localforage-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import localForage from 'localforage';
import centroid from '@turf/centroid';
import {
IappRecordMode,
RecordCacheAddSpec,
RepositoryMetadata,
RecordCacheService,
RecordSetSourceMetadata
} from 'utils/record-cache/index';
Expand Down Expand Up @@ -34,22 +34,22 @@ class LocalForageRecordCacheService extends RecordCacheService {

async isCached(repositoryId: string): Promise<boolean> {
try {
return (await this.fetchRepository(repositoryId)).status === UserRecordCacheStatus.CACHED;
return (await this.getRepository(repositoryId)).status === UserRecordCacheStatus.CACHED;
} catch (e) {
return false;
}
}

async fetchRepository(repositoryId: string): Promise<RecordCacheAddSpec> {
async getRepository(repositoryId: string): Promise<RepositoryMetadata> {
const repos = await this.listRepositories();
const foundIndex = repos.findIndex((p) => p.setId === repositoryId);
if (foundIndex === -1) throw Error(`Repository ${repositoryId} not found`);

return repos[foundIndex];
}

async fetchIdList(repositoryId: string): Promise<string[]> {
return (await this.fetchRepository(repositoryId)).cachedIds ?? [];
async getIdList(repositoryId: string): Promise<string[]> {
return (await this.getRepository(repositoryId)).cachedIds ?? [];
}

async saveActivity(id: string, data: unknown): Promise<void> {
Expand Down Expand Up @@ -80,6 +80,7 @@ class LocalForageRecordCacheService extends RecordCacheService {
}
return true;
}

async saveIapp(id: string, iappRecord: IappRecord, iappTableRow: IappTableRow): Promise<void> {
if (this.store == null) {
throw new Error('cache not available');
Expand All @@ -99,7 +100,7 @@ class LocalForageRecordCacheService extends RecordCacheService {
return data[type];
}

async fetchPaginatedCachedIappRecords(
async getPaginatedCachedIappRecords(
recordSetIdList: string[],
page: number,
limit: number,
Expand Down Expand Up @@ -139,7 +140,11 @@ class LocalForageRecordCacheService extends RecordCacheService {
* @param limit Maximum results per page
* @returns { UserRecord[] } Filter Objects
*/
async fetchPaginatedCachedRecords(recordSetIdList: string[], page: number, limit: number): Promise<UserRecord[]> {
async getPaginatedCachedActivityRecords(
recordSetIdList: string[],
page: number,
limit: number
): Promise<UserRecord[]> {
if (recordSetIdList?.length === 0) {
return [];
}
Expand All @@ -159,7 +164,7 @@ class LocalForageRecordCacheService extends RecordCacheService {
* @param ids ids to filter
* @returns { RecordSetSourceMetadata } Returns cached GeoJson, all IAPP Sites are Points.
*/
async loadIappRecordsetSourceMetadata(ids: string[]): Promise<RecordSetSourceMetadata> {
async createIappRecordsetSourceMetadata(ids: string[]): Promise<RecordSetSourceMetadata> {
const geoJsonArr: any[] = [];
for (const id of ids) {
const data: IappRecord = await this.loadIapp(id, IappRecordMode.Row);
Expand All @@ -183,7 +188,7 @@ class LocalForageRecordCacheService extends RecordCacheService {
* @param ids ids to filter
* @returns { RecordSetSourceMetadata } Two formatted queries for High/Low zoom layers
*/
async loadRecordsetSourceMetadata(ids: string[]): Promise<RecordSetSourceMetadata> {
async createActivityRecordsetSourceMetadata(ids: string[]): Promise<RecordSetSourceMetadata> {
const centroidArr: any[] = [];
const geoJsonArr: any[] = [];

Expand Down Expand Up @@ -257,7 +262,7 @@ class LocalForageRecordCacheService extends RecordCacheService {
* @desc Create or Update an entry in the cachedSet Repository
* @param newSet Data to update
*/
async addOrUpdateRepository(newSet: RecordCacheAddSpec): Promise<void> {
async addOrUpdateRepository(newSet: RepositoryMetadata): Promise<void> {
if (this.store == null) {
throw new Error('cache not available');
}
Expand All @@ -273,12 +278,12 @@ class LocalForageRecordCacheService extends RecordCacheService {
await this.store.setItem(LocalForageRecordCacheService.CACHED_SETS_METADATA_KEY, cachedSets);
}

async listRepositories(): Promise<RecordCacheAddSpec[]> {
async listRepositories(): Promise<RepositoryMetadata[]> {
if (this.store == null) {
return [];
}

const metadata: RecordCacheAddSpec[] =
const metadata: RepositoryMetadata[] =
(await this.store.getItem(LocalForageRecordCacheService.CACHED_SETS_METADATA_KEY)) ?? [];
if (metadata == null) {
console.error('expected key not found');
Expand Down
Loading

0 comments on commit 3bdab17

Please sign in to comment.