mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-22 23:53:48 +01:00
Merge pull request #2657 from theit8514/grandparent-script-cache
Remove dependents from cache when dependency updated
This commit is contained in:
commit
8df950721c
@ -82,6 +82,16 @@ export async function executeJSScript(
|
|||||||
return loadedModule.main(ns);
|
return loadedModule.main(ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isDependencyOutOfDate(filename: string, scripts: Script[], scriptModuleSequenceNumber: number): boolean {
|
||||||
|
const depScript = scripts.find((s) => s.filename == filename);
|
||||||
|
|
||||||
|
// If the script is not present on the server, we should recompile, if only to get any necessary
|
||||||
|
// compilation errors.
|
||||||
|
if (!depScript) return true;
|
||||||
|
|
||||||
|
const depIsMoreRecent = depScript.moduleSequenceNumber > scriptModuleSequenceNumber;
|
||||||
|
return depIsMoreRecent;
|
||||||
|
}
|
||||||
/** Returns whether we should compile the script parameter.
|
/** Returns whether we should compile the script parameter.
|
||||||
*
|
*
|
||||||
* @param {Script} script
|
* @param {Script} script
|
||||||
@ -89,16 +99,7 @@ export async function executeJSScript(
|
|||||||
*/
|
*/
|
||||||
function shouldCompile(script: Script, scripts: Script[]): boolean {
|
function shouldCompile(script: Script, scripts: Script[]): boolean {
|
||||||
if (script.module === "") return true;
|
if (script.module === "") return true;
|
||||||
return script.dependencies.some((dep) => {
|
return script.dependencies.some((dep) => isDependencyOutOfDate(dep.filename, scripts, script.moduleSequenceNumber));
|
||||||
const depScript = scripts.find((s) => s.filename == dep.filename);
|
|
||||||
|
|
||||||
// If the script is not present on the server, we should recompile, if only to get any necessary
|
|
||||||
// compilation errors.
|
|
||||||
if (!depScript) return true;
|
|
||||||
|
|
||||||
const depIsMoreRecent = depScript.moduleSequenceNumber > script.moduleSequenceNumber;
|
|
||||||
return depIsMoreRecent;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gets a stack of blob urls, the top/right-most element being
|
// Gets a stack of blob urls, the top/right-most element being
|
||||||
@ -123,8 +124,13 @@ function shouldCompile(script: Script, scripts: Script[]): boolean {
|
|||||||
// BUG: apparently seen is never consulted. Oops.
|
// BUG: apparently seen is never consulted. Oops.
|
||||||
function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): ScriptUrl[] {
|
function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): ScriptUrl[] {
|
||||||
// Inspired by: https://stackoverflow.com/a/43834063/91401
|
// Inspired by: https://stackoverflow.com/a/43834063/91401
|
||||||
/** @type {ScriptUrl[]} */
|
const urlStack: ScriptUrl[] = [];
|
||||||
const urlStack = [];
|
// Seen contains the dependents of the current script. Make sure we include that in the script dependents.
|
||||||
|
for (const dependent of seen) {
|
||||||
|
if (!script.dependents.some(s => s.server === dependent.server && s.filename == dependent.filename)) {
|
||||||
|
script.dependents.push({ server: dependent.server, filename: dependent.filename });
|
||||||
|
}
|
||||||
|
}
|
||||||
seen.push(script);
|
seen.push(script);
|
||||||
try {
|
try {
|
||||||
// Replace every import statement with an import to a blob url containing
|
// Replace every import statement with an import to a blob url containing
|
||||||
@ -187,6 +193,19 @@ function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): Scri
|
|||||||
// Check to see if the urls for this script are stored in the cache by the hash value.
|
// Check to see if the urls for this script are stored in the cache by the hash value.
|
||||||
let urls = ImportCache.get(importedScript.hash());
|
let urls = ImportCache.get(importedScript.hash());
|
||||||
// If we don't have it in the cache, then we need to generate the urls for it.
|
// If we don't have it in the cache, then we need to generate the urls for it.
|
||||||
|
if (urls) {
|
||||||
|
// Verify that these urls are valid and have not been updated.
|
||||||
|
for(const url of urls) {
|
||||||
|
if (isDependencyOutOfDate(url.filename, scripts, url.moduleSequenceNumber)) {
|
||||||
|
// Revoke these URLs from the browser. We will be unable to use them again.
|
||||||
|
for (const url of urls) URL.revokeObjectURL(url.url);
|
||||||
|
// Clear the cache and prepare for new blobs.
|
||||||
|
urls = null;
|
||||||
|
ImportCache.remove(importedScript.hash());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!urls) {
|
if (!urls) {
|
||||||
// Try to get a URL for the requested script and its dependencies.
|
// Try to get a URL for the requested script and its dependencies.
|
||||||
urls = _getScriptUrls(importedScript, scripts, seen);
|
urls = _getScriptUrls(importedScript, scripts, seen);
|
||||||
@ -217,7 +236,7 @@ function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): Scri
|
|||||||
// (e.g. same scripts on server, same hash value, etc) can use this blob url.
|
// (e.g. same scripts on server, same hash value, etc) can use this blob url.
|
||||||
BlobCache.store(transformedHash, blob);
|
BlobCache.store(transformedHash, blob);
|
||||||
// Push the blob URL onto the top of the stack.
|
// Push the blob URL onto the top of the stack.
|
||||||
urlStack.push(new ScriptUrl(script.filename, blob));
|
urlStack.push(new ScriptUrl(script.filename, blob, script.moduleSequenceNumber));
|
||||||
return urlStack;
|
return urlStack;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// If there is an error, we need to clean up the URLs.
|
// If there is an error, we need to clean up the URLs.
|
||||||
|
@ -10,10 +10,13 @@ import { ScriptUrl } from "./ScriptUrl";
|
|||||||
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
import { Generic_fromJSON, Generic_toJSON, Reviver } from "../utils/JSONReviver";
|
||||||
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
||||||
import { computeHash } from "../utils/helpers/computeHash";
|
import { computeHash } from "../utils/helpers/computeHash";
|
||||||
|
import { ImportCache } from "../utils/ImportCache";
|
||||||
import { IPlayer } from "../PersonObjects/IPlayer";
|
import { IPlayer } from "../PersonObjects/IPlayer";
|
||||||
|
|
||||||
let globalModuleSequenceNumber = 0;
|
let globalModuleSequenceNumber = 0;
|
||||||
|
|
||||||
|
interface ScriptReference { filename: string; server: string }
|
||||||
|
|
||||||
export class Script {
|
export class Script {
|
||||||
// Code for this script
|
// Code for this script
|
||||||
code = "";
|
code = "";
|
||||||
@ -35,6 +38,7 @@ export class Script {
|
|||||||
// whenever the script is first evaluated, and therefore may be out of date if the script
|
// whenever the script is first evaluated, and therefore may be out of date if the script
|
||||||
// has been updated since it was last run.
|
// has been updated since it was last run.
|
||||||
dependencies: ScriptUrl[] = [];
|
dependencies: ScriptUrl[] = [];
|
||||||
|
dependents: ScriptReference[] = [];
|
||||||
|
|
||||||
// Amount of RAM this Script requres to run
|
// Amount of RAM this Script requres to run
|
||||||
ramUsage = 0;
|
ramUsage = 0;
|
||||||
@ -99,7 +103,11 @@ export class Script {
|
|||||||
* Force update of the computed hash based on the source code.
|
* Force update of the computed hash based on the source code.
|
||||||
*/
|
*/
|
||||||
rehash(): void {
|
rehash(): void {
|
||||||
|
const oldHash = this._hash;
|
||||||
this._hash = computeHash(this.code);
|
this._hash = computeHash(this.code);
|
||||||
|
if (oldHash !== this._hash) {
|
||||||
|
ImportCache.remove(oldHash);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,6 +132,10 @@ export class Script {
|
|||||||
this.server = hostname;
|
this.server = hostname;
|
||||||
this.updateRamUsage(player, otherScripts);
|
this.updateRamUsage(player, otherScripts);
|
||||||
this.markUpdated();
|
this.markUpdated();
|
||||||
|
for (const dependent of this.dependents) {
|
||||||
|
const [dependentScript] = otherScripts.filter(s => s.filename === dependent.filename && s.server == dependent.server);
|
||||||
|
if (dependentScript !== null) dependentScript.markUpdated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -156,6 +168,7 @@ export class Script {
|
|||||||
s.url = "";
|
s.url = "";
|
||||||
// Rehash the code to ensure that hash is set properly.
|
// Rehash the code to ensure that hash is set properly.
|
||||||
s.rehash();
|
s.rehash();
|
||||||
|
s.dependents = [];
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
export class ScriptUrl {
|
export class ScriptUrl {
|
||||||
filename: string;
|
filename: string;
|
||||||
url: string;
|
url: string;
|
||||||
|
moduleSequenceNumber: number;
|
||||||
|
|
||||||
constructor(filename: string, url: string) {
|
constructor(filename: string, url: string, moduleSequenceNumber: number) {
|
||||||
this.filename = filename;
|
this.filename = filename;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
this.moduleSequenceNumber = moduleSequenceNumber;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,16 @@ import { ScriptUrl } from "../Script/ScriptUrl";
|
|||||||
const importCache: { [hash: string]: ScriptUrl[] } = {};
|
const importCache: { [hash: string]: ScriptUrl[] } = {};
|
||||||
|
|
||||||
export class ImportCache {
|
export class ImportCache {
|
||||||
static get(hash: string): ScriptUrl[] {
|
static get(hash: string): ScriptUrl[] | null {
|
||||||
return importCache[hash];
|
return importCache[hash] || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static store(hash: string, value: ScriptUrl[]): void {
|
static store(hash: string, value: ScriptUrl[]): void {
|
||||||
if (importCache[hash]) return;
|
if (importCache[hash]) return;
|
||||||
importCache[hash] = value;
|
importCache[hash] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static remove(hash: string): void {
|
||||||
|
delete importCache[hash];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user