mirror of https://github.com/rancher/dashboard.git
130 lines
3.4 KiB
JavaScript
130 lines
3.4 KiB
JavaScript
import * as Comlink from 'comlink';
|
|
import { SCHEMA } from '@shell/config/types';
|
|
|
|
const COUNTS_FLUSH_TIMEOUT = 5000;
|
|
const SCHEMA_FLUSH_TIMEOUT = 2500;
|
|
|
|
const state = {
|
|
store: '', // Store name
|
|
load: undefined, // Load callback to load a resource into the store
|
|
counts: [], // Buffer of count resources recieved in a given window
|
|
countTimer: undefined, // Tiemr to flush the count buffer
|
|
flushTimer: undefined, // Timer to flush the schema chaneg queue
|
|
queue: [], // Schema change queue
|
|
schemas: {} // Map of schema id to hash to track when a schema actually changes
|
|
};
|
|
|
|
// Quick, simple hash function
|
|
function hash(str) {
|
|
let hash = 0;
|
|
|
|
for (let i = 0; i < str.length; i++) {
|
|
const char = str.charCodeAt(i);
|
|
|
|
hash = (hash << 5) - hash + char;
|
|
hash &= hash;
|
|
}
|
|
|
|
return new Uint32Array([hash])[0].toString(36);
|
|
}
|
|
|
|
// Quick, simple hash function to generate hash for an object
|
|
function hashObj(obj) {
|
|
return hash(JSON.stringify(obj, null, 2));
|
|
}
|
|
|
|
function flush() {
|
|
state.queue.forEach((schema) => {
|
|
const hash = hashObj(schema);
|
|
const existing = state.schemas[schema.id];
|
|
|
|
if (!existing || (existing && existing !== hash)) {
|
|
// console.log(`${ schema.id } CHANGED ${ hash } > ${ existing }`);
|
|
state.schemas[schema.id] = hash;
|
|
|
|
const msg = {
|
|
data: schema,
|
|
resourceType: SCHEMA,
|
|
type: 'resource.change'
|
|
};
|
|
|
|
load(msg);
|
|
}
|
|
});
|
|
|
|
state.queue = [];
|
|
|
|
state.flushTimer = setTimeout(flush, SCHEMA_FLUSH_TIMEOUT);
|
|
}
|
|
|
|
state.flushTimer = setTimeout(flush, SCHEMA_FLUSH_TIMEOUT);
|
|
|
|
// Callback to the store's load function (in the main thread) to process a load
|
|
function load(data) {
|
|
if (state.load) {
|
|
state.load(data);
|
|
}
|
|
}
|
|
|
|
// Web Worker API
|
|
const fns = {
|
|
initWorker(storeName, loadFn) {
|
|
state.store = storeName;
|
|
state.load = loadFn;
|
|
},
|
|
|
|
destroyWorker() {
|
|
clearTimeout(state.countTimer);
|
|
clearTimeout(state.flushTimer);
|
|
|
|
// Web worker global function to terminate the web worker
|
|
close();
|
|
},
|
|
|
|
// Debounce counts messages so we only process at most 1 every 5 seconds
|
|
countsUpdate(resource) {
|
|
state.counts.push(resource);
|
|
|
|
if (!state.countTimer) {
|
|
state.countTimer = setTimeout(() => {
|
|
const last = state.counts.pop();
|
|
|
|
state.counts = [];
|
|
state.countTimer = null;
|
|
|
|
load(last);
|
|
}, COUNTS_FLUSH_TIMEOUT);
|
|
}
|
|
},
|
|
|
|
// Called to load schema
|
|
loadSchema(schemas) {
|
|
schemas.forEach((schema) => {
|
|
// These properties are added to the object, but aren't on the raw object, so remove them
|
|
// otherwise our comparison will show changes when there aren't any
|
|
delete schema._id;
|
|
delete schema._group;
|
|
|
|
state.schemas[schema.id] = hashObj(schema);
|
|
});
|
|
},
|
|
|
|
// Called when schema is updated
|
|
updateSchema(schema) {
|
|
// Add the schema to the queue to be checked to see if the schema really changed
|
|
state.queue.push(schema);
|
|
},
|
|
|
|
// Remove the cached schema
|
|
removeSchema(id) {
|
|
// Remove anything in the queue related to the schema - we don't want to send any pending updates later for a schema that has been removed
|
|
state.queue = state.queue.filter(schema => schema.id !== id);
|
|
|
|
// Delete the schema from the map, so if it comes back we don't ignore it if the hash is the same
|
|
delete state.schemas[id];
|
|
}
|
|
};
|
|
|
|
// Expose the Web Worker API - see: https://github.com/GoogleChromeLabs/comlink
|
|
Comlink.expose(fns);
|