Skip to content

Commit

Permalink
Implement local cache
Browse files Browse the repository at this point in the history
  • Loading branch information
agviegas committed Feb 20, 2023
1 parent c34202e commit 8c1bf5d
Show file tree
Hide file tree
Showing 7 changed files with 118 additions and 6 deletions.
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"client-zip": "^2.3.0",
"dexie": "^3.2.3",
"firebase": "^9.17.1",
"mapbox-gl": "^2.12.1",
"openbim-components": "^0.0.39",
Expand Down
81 changes: 76 additions & 5 deletions src/core/building/building-database.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,91 @@
import { ModelDatabase } from "./dexie-utils";
import { getApp } from "firebase/app";
import { getDownloadURL, getStorage, ref } from "firebase/storage";
import {
FirebaseStorage,
getDownloadURL,
getStorage,
ref,
} from "firebase/storage";
import { Building } from "../../types";

// CORS problem solution: https://stackoverflow.com/a/58613527
export class BuildingDatabase {
private db: ModelDatabase;

constructor() {
this.db = new ModelDatabase();
}

async getModels(building: Building) {
const appInstance = getApp();
const storageInstance = getStorage(appInstance);
const instance = getStorage(appInstance);

const urls: string[] = [];
for (const model of building.models) {
const fileRef = ref(storageInstance, model.id);
const fileUrl = await getDownloadURL(fileRef);
urls.push(fileUrl);
const url = await this.getModelURL(instance, model.id);
urls.push(url);
}

this.db.close();

return urls;
}

async clearCache(building: Building) {
await this.db.open();
for (const model of building.models) {
localStorage.removeItem(model.id);
}
await this.db.delete();
this.db = new ModelDatabase();
this.db.close();
}

async deleteModel(id: string) {
await this.db.open();
if (this.isModelCached(id)) {
localStorage.removeItem(id);
await this.db.models.where("id").equals(id).delete();
}
this.db.close();
}

private async getModelURL(instance: FirebaseStorage, id: string) {
if (this.isModelCached(id)) {
return this.getModelFromLocalCache(id);
} else {
return this.getModelFromFirebase(instance, id);
}
}

private async getModelFromFirebase(instance: FirebaseStorage, id: string) {
const fileRef = ref(instance, id);
const url = await getDownloadURL(fileRef);
await this.cacheModel(id, url);
console.log("Got model from firebase!");
return url;
}

private async getModelFromLocalCache(id: string) {
const found = await this.db.models.where("id").equals(id).toArray();
const file = found[0].file;
console.log("Got model from local cache!");
return URL.createObjectURL(file);
}

private isModelCached(id: string) {
const stored = localStorage.getItem(id);
return stored !== null;
}

private async cacheModel(id: string, url: string) {
const time = performance.now().toString();
localStorage.setItem(id, time);
const rawData = await fetch(url);
const file = await rawData.blob();
await this.db.models.add({
id,
file,
});
}
}
6 changes: 6 additions & 0 deletions src/core/building/building-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@ export const buildingHandler = {
}
return this.viewer.convertIfcToFragments(ifc);
},

async deleteModel(id: string) {
if (this.viewer) {
await this.viewer.database.deleteModel(id);
}
},
};
2 changes: 1 addition & 1 deletion src/core/building/building-scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { unzip } from "unzipit";
export class BuildingScene {
private components: OBC.Components;
private fragments: OBC.Fragments;
private database = new BuildingDatabase();
database = new BuildingDatabase();

constructor(container: HTMLDivElement, building: Building) {
this.components = new OBC.Components();
Expand Down
17 changes: 17 additions & 0 deletions src/core/building/dexie-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Dexie } from "dexie";

interface IModel {
id: string;
file: Blob;
}

export class ModelDatabase extends Dexie {
models!: Dexie.Table<IModel, number>;

constructor() {
super("ModelDatabase");
this.version(2).stores({
models: "id, file",
});
}
}
3 changes: 3 additions & 0 deletions src/core/database/db-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { deleteDoc, doc, getFirestore, updateDoc } from "firebase/firestore";
import { Events } from "../../middleware/event-handler";
import { Building, Model } from "../../types";
import { getStorage, ref, uploadBytes, deleteObject } from "firebase/storage";
import { buildingHandler } from "../building/building-handler";

export const databaseHandler = {
login: () => {
Expand All @@ -31,6 +32,7 @@ export const databaseHandler = {
for (const model of building.models) {
const fileRef = ref(storageInstance, model.id);
await deleteObject(fileRef);
await buildingHandler.deleteModel(model.id);
}
events.trigger({ type: "CLOSE_BUILDING" });
},
Expand Down Expand Up @@ -60,6 +62,7 @@ export const databaseHandler = {
const storageInstance = getStorage(appInstance);
const fileRef = ref(storageInstance, model.id);
await deleteObject(fileRef);
await buildingHandler.deleteModel(model.id);
events.trigger({ type: "UPDATE_BUILDING", payload: building });
},
};

0 comments on commit 8c1bf5d

Please sign in to comment.