This repository has been archived on 2021-02-20. You can view files and clone it, but cannot push or open issues or pull requests.
shapez.io/src/js/core/async_compression.js

113 lines
3.2 KiB
JavaScript

// @ts-ignore
import CompressionWorker from "../webworkers/compression.worker";
import { createLogger } from "./logging";
import { round2Digits } from "./utils";
const logger = createLogger("async_compression");
export let compressionPrefix = String.fromCodePoint(1);
function checkCryptPrefix(prefix) {
try {
window.localStorage.setItem("prefix_test", prefix);
window.localStorage.removeItem("prefix_test");
return true;
} catch (ex) {
logger.warn("Prefix '" + prefix + "' not available");
return false;
}
}
if (!checkCryptPrefix(compressionPrefix)) {
logger.warn("Switching to basic prefix");
compressionPrefix = " ";
if (!checkCryptPrefix(compressionPrefix)) {
logger.warn("Prefix not available, ls seems to be unavailable");
}
}
/**
* @typedef {{
* errorHandler: function(any) : void,
* resolver: function(any) : void,
* startTime: number
* }} JobEntry
*/
class AsynCompression {
constructor() {
this.worker = new CompressionWorker();
this.currentJobId = 1000;
/** @type {Object.<number, JobEntry>} */
this.currentJobs = {};
this.worker.addEventListener("message", event => {
const { jobId, result } = event.data;
const jobData = this.currentJobs[jobId];
if (!jobData) {
logger.error("Failed to resolve job result, job id", jobId, "is not known");
return;
}
const duration = performance.now() - jobData.startTime;
logger.log("Got job", jobId, "response within", round2Digits(duration), "ms");
const resolver = jobData.resolver;
delete this.currentJobs[jobId];
resolver(result);
});
this.worker.addEventListener("error", err => {
logger.error("Got error from webworker:", err, "aborting all jobs");
const failureCalls = [];
for (const jobId in this.currentJobs) {
failureCalls.push(this.currentJobs[jobId].errorHandler);
}
this.currentJobs = {};
for (let i = 0; i < failureCalls.length; ++i) {
failureCalls[i](err);
}
});
}
/**
* Compresses file
* @param {string} text
*/
compressFileAsync(text) {
logger.log("Compressing", text.length, "bytes async");
return this.internalQueueJob("compressFile", {
text,
compressionPrefix,
});
}
/**
* Queues a new job
* @param {string} job
* @param {any} data
* @returns {Promise<any>}
*/
internalQueueJob(job, data) {
const jobId = ++this.currentJobId;
return new Promise((resolve, reject) => {
const errorHandler = err => {
logger.error("Failed to compress job", jobId, ":", err);
reject(err);
};
this.currentJobs[jobId] = {
errorHandler,
resolver: resolve,
startTime: performance.now(),
};
logger.log("Posting job", job, "/", jobId);
this.worker.postMessage({ jobId, job, data });
});
}
}
export const asyncCompressor = new AsynCompression();