@volter/twin-world 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/resources.ts +17 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/twin-world",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "World configs for twins: boot named local runtimes, allocate ports, generate world.env/instance.json, and run apps against fake-key twin worlds.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"twin",
|
package/src/resources.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statfsSync, writeFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, statfsSync, statSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
3
|
import { homedir, hostname, totalmem } from 'node:os';
|
|
4
4
|
import { dirname, join, resolve } from 'node:path';
|
|
@@ -13,6 +13,7 @@ export const DEFAULT_WORLD_RESOURCES: WorldResourceRequirements = {
|
|
|
13
13
|
|
|
14
14
|
export type WorldResourceClaim = {
|
|
15
15
|
world: string;
|
|
16
|
+
root?: string;
|
|
16
17
|
identity: string;
|
|
17
18
|
ownerPid: number;
|
|
18
19
|
holderPids: number[];
|
|
@@ -77,7 +78,17 @@ function writePrivate(path: string, contents: string): void {
|
|
|
77
78
|
writeFileSync(path, contents, { mode: 0o600 });
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
+
/** Resolve old claims without rewriting them. Unknown locations stay charged on every
|
|
82
|
+
* filesystem rather than silently allowing a reservation we cannot locate. */
|
|
83
|
+
function sharesStorage(root: string, claim: WorldResourceClaim): boolean {
|
|
84
|
+
try {
|
|
85
|
+
const claimRoot = claim.root ?? resolve(dirname(claim.log), '../../..');
|
|
86
|
+
if (claimIdentity(claimRoot, claim.world) !== claim.identity) return true;
|
|
87
|
+
return statSync(claimRoot).dev === statSync(root).dev;
|
|
88
|
+
} catch { return true; }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function worldResourceCapacity(root: string, claims: WorldResourceClaim[]): WorldResourceRequirements {
|
|
81
92
|
const fs = statfsSync(resolve(root));
|
|
82
93
|
const diskFreeMiB = Math.floor((Number(fs.bavail) * Number(fs.bsize)) / MIB);
|
|
83
94
|
const memoryTotalMiB = Math.floor(totalmem() / MIB);
|
|
@@ -85,7 +96,8 @@ function capacity(root: string, claims: WorldResourceClaim[]): WorldResourceRequ
|
|
|
85
96
|
const diskTotalMiB = Math.floor((Number(fs.blocks) * Number(fs.bsize)) / MIB);
|
|
86
97
|
const diskSafetyMiB = Math.max(512, Math.min(2048, Math.floor(diskTotalMiB * 0.05)));
|
|
87
98
|
const reservedMemoryMiB = claims.reduce((sum, claim) => sum + claim.resources.memoryMiB, 0);
|
|
88
|
-
const reservedDiskMiB = claims.
|
|
99
|
+
const reservedDiskMiB = claims.filter((claim) => sharesStorage(root, claim))
|
|
100
|
+
.reduce((sum, claim) => sum + claim.resources.writableStorageMiB, 0);
|
|
89
101
|
return {
|
|
90
102
|
memoryMiB: Math.max(0, memoryTotalMiB - memorySafetyMiB - reservedMemoryMiB),
|
|
91
103
|
writableStorageMiB: Math.max(0, diskFreeMiB - diskSafetyMiB - reservedDiskMiB),
|
|
@@ -106,7 +118,7 @@ export function claimWorldResources(root: string, world: string, requested: Worl
|
|
|
106
118
|
return withFileLock(join(dir, 'claims.lock'), () => {
|
|
107
119
|
const identity = claimIdentity(root, world);
|
|
108
120
|
const claims = liveClaims(identity);
|
|
109
|
-
const available =
|
|
121
|
+
const available = worldResourceCapacity(root, claims);
|
|
110
122
|
const shortages: string[] = [];
|
|
111
123
|
if (requested.memoryMiB > available.memoryMiB) shortages.push(`memory requires ${requested.memoryMiB} MiB, ${available.memoryMiB} MiB available`);
|
|
112
124
|
if (requested.writableStorageMiB > available.writableStorageMiB) {
|
|
@@ -120,6 +132,7 @@ export function claimWorldResources(root: string, world: string, requested: Worl
|
|
|
120
132
|
}
|
|
121
133
|
const claim: WorldResourceClaim = {
|
|
122
134
|
world,
|
|
135
|
+
root: resolve(root),
|
|
123
136
|
identity,
|
|
124
137
|
ownerPid: process.pid,
|
|
125
138
|
holderPids: [],
|