mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-11-14 00:07:00 +01:00
71 lines
4.7 KiB
JavaScript
71 lines
4.7 KiB
JavaScript
/* Reproducible local acceptance workload. Never connects to production or downloads upstream files. */
|
|
const { strict: assert } = require("node:assert");
|
|
const { promises: fs } = require("node:fs");
|
|
const { tmpdir } = require("node:os");
|
|
const { join } = require("node:path");
|
|
const { Readable } = require("node:stream");
|
|
const { createHash } = require("node:crypto");
|
|
const http = require("node:http");
|
|
const express = require("express");
|
|
require("ts-node/register/transpile-only");
|
|
const config = require("../src/config").default;
|
|
const { BlobCache, sharedBlobCache, resultBlobCache, closeBlobCaches } = require("../src/core/blob-cache");
|
|
const { sendSharedContent } = require("../src/core/cached-response");
|
|
const { cacheMetricsReport, closeCacheMetrics } = require("../src/core/cache-observability");
|
|
const { monitorRequests } = require("../src/core/request-monitoring");
|
|
const consume = async s => { const chunks = []; for await (const b of s) chunks.push(Buffer.from(b)); return Buffer.concat(chunks); };
|
|
async function main() {
|
|
const root = await fs.mkdtemp(join(tmpdir(), "cache-workload-")); let server, eviction;
|
|
const old = { ...config };
|
|
Object.assign(config, { SHARED_CACHE_ENABLED: true, SHARED_CACHE_PATH: root, SHARED_CACHE_BYTES: 1024 * 1024,
|
|
SHARED_CACHE_RESULT_BYTES: 1024 * 1024, SHARED_CACHE_MAX_FILE_BYTES: 32768, SHARED_CACHE_FREE_BYTES: 0, CACHE_MONITORING_ENABLED: true });
|
|
try {
|
|
const source = sharedBlobCache();
|
|
const content = Buffer.from("A public example with repeatable documentation.\n".repeat(400));
|
|
const key = "git-" + createHash("sha1").update(`blob ${content.length}\0`).update(content).digest("hex");
|
|
let fills = 0;
|
|
const obtain = () => source.getOrFill(key, async () => { fills++; return Readable.from(content); }, async p => {
|
|
assert.equal(key, "git-" + p.gitSha); return key;
|
|
}, content.length);
|
|
const app = express(); app.use(monitorRequests("api", undefined, { info() {}, warn() {} }));
|
|
app.get("/:project/:rule", async (req, res) => {
|
|
res.type("text/plain");
|
|
try { assert.equal(await sendSharedContent(await obtain(), res, { filePath: "README.md", repoId: req.params.project,
|
|
terms: req.params.rule === "changed" ? ["public=>private"] : ["Alice"] }), true); }
|
|
catch (e) { res.destroy(e); }
|
|
});
|
|
await new Promise(resolve => { server = app.listen(0, "127.0.0.1", resolve); });
|
|
const responses = [];
|
|
for (const path of ["/a/plain", "/b/plain", "/a/plain", "/a/changed", "/a/changed"]) {
|
|
responses.push(await new Promise((resolve, reject) => {
|
|
http.get({ host: "127.0.0.1", port: server.address().port, path, headers: { "accept-encoding": "gzip" } }, res => {
|
|
consume(res).then(b => resolve({ status: res.statusCode, encoding: res.headers["content-encoding"], bytes: b.length }), reject);
|
|
}).on("error", reject);
|
|
}));
|
|
}
|
|
assert.equal(fills, 1); assert.ok(responses.every(r => r.status === 200 && r.encoding === "gzip"));
|
|
eviction = new BlobCache({ root: join(root, "eviction"), budget: 65536, maxObject: 4096, gzip: false, name: "workload" });
|
|
for (let i = 0; i < 30; i++) {
|
|
const data = Buffer.alloc(4000, i);
|
|
await consume(await eviction.getOrFill(`item-${i}`, async () => Readable.from(data)));
|
|
const stats = eviction.stats(); assert.ok(stats.allocatedBytes + stats.reservedBytes <= stats.budgetBytes);
|
|
}
|
|
const stats = eviction.stats(); assert.ok(stats.blobs < 30);
|
|
const metrics = cacheMetricsReport(60);
|
|
const count = name => metrics.rows.filter(r => r.name === name).reduce((n, r) => n + r.count, 0);
|
|
assert.equal(count("decision_hit"), 2); assert.equal(count("rewrite_changed"), 1);
|
|
const result = { node: process.version, measuredAt: new Date().toISOString(), scope: "Synthetic local acceptance workload; not a production projection",
|
|
sourceRequests: 5, upstreamFills: fills, source: source.stats(), results: resultBlobCache().stats(), eviction: stats,
|
|
decisionsReused: count("decision_hit"), unchangedDecisionsComputed: count("rewrite_unchanged"), changedOutputsComputed: count("rewrite_changed"),
|
|
compressionSavingPercent: 100 * (1 - source.stats().storedBytes / source.stats().originalBytes), responses, metrics: metrics.rows,
|
|
assertions: "passed" };
|
|
const json = JSON.stringify(result, null, 2) + "\n";
|
|
if (process.argv[2]) await fs.writeFile(process.argv[2], json);
|
|
process.stdout.write(json);
|
|
} finally {
|
|
if (server) await new Promise(resolve => server.close(resolve));
|
|
eviction?.close(); closeBlobCaches(); closeCacheMetrics(); Object.assign(config, old); await fs.rm(root, { recursive: true, force: true });
|
|
}
|
|
}
|
|
main().catch(e => { console.error(e); process.exitCode = 1; });
|