mirror of https://github.com/rancher/dashboard.git
117 lines
3.7 KiB
JavaScript
117 lines
3.7 KiB
JavaScript
import { SCHEMA } from '@shell/config/types';
|
|
import { hashObj } from '@shell/utils/crypto/browserHashUtils';
|
|
import { removeSchemaIndexFields } from '@shell/plugins/steve/schema.utils';
|
|
|
|
const SCHEMA_FLUSH_TIMEOUT = 2500;
|
|
|
|
const state = {
|
|
store: '', // Store name
|
|
flushTimer: undefined, // Timer to flush the schema change queue
|
|
queue: [], // Schema change queue
|
|
schemas: {} // Map of schema id to hash to track when a schema actually changes
|
|
};
|
|
|
|
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) {
|
|
self.postMessage({ load: data });
|
|
}
|
|
|
|
// used for dispatching a function in the worker, primarily for redirecting messages intended for the advanced worker back to the UI thread
|
|
function redispatch(msg) {
|
|
self.postMessage({ redispatch: msg });
|
|
}
|
|
|
|
/**
|
|
* These actions aren't applicable to the basic worker, so bounce back to ui thread
|
|
*
|
|
* These are called when a queue of actions is flushed. Queue is populated from requests made before we know if worker is basic or advanced.
|
|
*/
|
|
const advancedWorkerActions = {
|
|
watch: (msg) => {
|
|
redispatch({ send: msg });
|
|
},
|
|
createWatcher: (msg) => {
|
|
redispatch({ subscribe: msg });
|
|
}
|
|
};
|
|
|
|
const workerActions = {
|
|
onmessage: (e) => {
|
|
/* on the off chance there's more than key in the message, we handle them in the order that they "keys" method provides which is
|
|
// good enough for now considering that we never send more than one message action at a time right now */
|
|
const messageActions = Object.keys(e?.data);
|
|
|
|
messageActions.forEach((action) => {
|
|
if (workerActions[action]) {
|
|
workerActions[action](e?.data[action]);
|
|
} else {
|
|
console.warn('no associated action for:', action); // eslint-disable-line no-console
|
|
}
|
|
});
|
|
},
|
|
initWorker: ({ storeName }) => {
|
|
state.store = storeName;
|
|
},
|
|
|
|
destroyWorker: () => {
|
|
clearTimeout(state.flushTimer);
|
|
|
|
self.postMessage({ destroyWorker: true }); // we're only passing the boolean here because the key needs to be something truthy to ensure it's passed on the object.
|
|
},
|
|
|
|
// Called to load schema
|
|
loadSchemas: (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
|
|
removeSchemaIndexFields(schema);
|
|
|
|
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];
|
|
},
|
|
...advancedWorkerActions
|
|
};
|
|
|
|
self.onmessage = workerActions.onmessage; // bind everything to the worker's onmessage handler via the workerAction
|