130 lines
4.1 KiB
JavaScript
130 lines
4.1 KiB
JavaScript
// job-cache.ts
|
|
var DB_NAME = "JobInfoCache";
|
|
var DB_VERSION = 2;
|
|
var JOBS_STORE = "jobs";
|
|
var META_STORE = "metadata";
|
|
var CACHE_TTL = 5 * 60 * 1000;
|
|
var PAGE_SIZE = 500;
|
|
|
|
class JobCache {
|
|
db = null;
|
|
async initialize() {
|
|
return new Promise((resolve, reject) => {
|
|
const request = indexedDB.open(DB_NAME, DB_VERSION);
|
|
request.onerror = () => reject(request.error);
|
|
request.onsuccess = () => {
|
|
this.db = request.result;
|
|
resolve();
|
|
};
|
|
request.onupgradeneeded = (event) => {
|
|
const db = event.target.result;
|
|
if (!db.objectStoreNames.contains(JOBS_STORE)) {
|
|
db.createObjectStore(JOBS_STORE, { keyPath: "Job_Number" });
|
|
}
|
|
if (!db.objectStoreNames.contains(META_STORE)) {
|
|
db.createObjectStore(META_STORE);
|
|
}
|
|
};
|
|
});
|
|
}
|
|
async getCachedJobs() {
|
|
if (!this.db)
|
|
throw new Error("Database not initialized");
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = this.db.transaction([JOBS_STORE], "readonly");
|
|
const store = transaction.objectStore(JOBS_STORE);
|
|
const request = store.getAll();
|
|
request.onsuccess = () => resolve(request.result);
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
async isCacheValid() {
|
|
if (!this.db)
|
|
return false;
|
|
try {
|
|
const metadata = await this.getMetadata();
|
|
if (!metadata || !metadata.lastUpdated)
|
|
return false;
|
|
const age = Date.now() - metadata.lastUpdated;
|
|
return age < CACHE_TTL;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
async saveJobs(jobs) {
|
|
if (!this.db)
|
|
throw new Error("Database not initialized");
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = this.db.transaction([JOBS_STORE, META_STORE], "readwrite");
|
|
const jobsStore = transaction.objectStore(JOBS_STORE);
|
|
const metaStore = transaction.objectStore(META_STORE);
|
|
jobsStore.clear();
|
|
jobs.forEach((job) => jobsStore.add(job));
|
|
const metadata = {
|
|
lastUpdated: Date.now(),
|
|
version: DB_VERSION
|
|
};
|
|
metaStore.put(metadata, "main");
|
|
transaction.oncomplete = () => resolve();
|
|
transaction.onerror = () => reject(transaction.error);
|
|
});
|
|
}
|
|
async refreshJobs() {
|
|
try {
|
|
let page = 1;
|
|
let all = [];
|
|
let totalPages = 1;
|
|
while (page <= totalPages) {
|
|
const url = `/api/jobs?page=${page}&perPage=${PAGE_SIZE}&sort=-Job_Number`;
|
|
const response = await fetch(url);
|
|
if (!response.ok) {
|
|
throw new Error(`Failed to fetch jobs (status ${response.status})`);
|
|
}
|
|
const data = await response.json();
|
|
const items = data.items || [];
|
|
const reportedTotalPages = data.totalPages || 1;
|
|
all = all.concat(items);
|
|
totalPages = Math.max(totalPages, reportedTotalPages);
|
|
page += 1;
|
|
}
|
|
await this.saveJobs(all);
|
|
return all;
|
|
} catch (err) {
|
|
console.error("Failed to refresh jobs cache:", err);
|
|
throw err;
|
|
}
|
|
}
|
|
async getMetadata() {
|
|
if (!this.db)
|
|
return null;
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = this.db.transaction([META_STORE], "readonly");
|
|
const store = transaction.objectStore(META_STORE);
|
|
const request = store.get("main");
|
|
request.onsuccess = () => resolve(request.result || null);
|
|
request.onerror = () => reject(request.error);
|
|
});
|
|
}
|
|
async clearCache() {
|
|
if (!this.db)
|
|
throw new Error("Database not initialized");
|
|
return new Promise((resolve, reject) => {
|
|
const transaction = this.db.transaction([JOBS_STORE, META_STORE], "readwrite");
|
|
transaction.objectStore(JOBS_STORE).clear();
|
|
transaction.objectStore(META_STORE).clear();
|
|
transaction.oncomplete = () => resolve();
|
|
transaction.onerror = () => reject(transaction.error);
|
|
});
|
|
}
|
|
async getCacheAge() {
|
|
const metadata = await this.getMetadata();
|
|
if (!metadata || !metadata.lastUpdated)
|
|
return null;
|
|
return Date.now() - metadata.lastUpdated;
|
|
}
|
|
}
|
|
var jobCache = new JobCache;
|
|
export {
|
|
jobCache
|
|
};
|