@struktoai/mirage-core
Version:
A Unified Virtual Filesystem For AI Agents
84 lines • 4.03 kB
JavaScript
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
import { isEnoent } from "../../errors/fs.js";
import { LookupStatus } from "./config.js";
import { indexLock } from "./lock.js";
import { rstripSlash } from "../../utils/slash.js";
/**
* Resolve an index entry, listing the parent directory once when its listing
* is missing or expired.
*
* Id-addressed backends (Drive, Box, Dropbox, Gmail) can only turn a path into
* an id through the index, so a cold lookup has to warm it from the parent's
* listing and retry. Every such backend had grown its own copy of that block;
* this is the one place that decides what a failed listing means.
*
* A missing parent listing does not prove a retained entry is current: a
* partial warm may have stored the child without publishing freshness. Such
* a child is dropped before the refresh. A fresh partial listing proves only
* the children it names; an omitted child still refreshes.
* A parent that is simply absent is not an error here — the caller reports
* ENOENT against the operand, which is the
* path GNU names (`rm nodir/f` says "cannot remove 'nodir/f'", not "nodir").
* Every other failure propagates: an expired token or a dropped connection
* reported as "no such file" both misdiagnoses the fault and hides that it is
* worth retrying.
*
* Mirrors Python's entry_or_warm.
*
* @param index - the index to read, and to warm through `warm`.
* @param virtualKey - the index key being resolved.
* @param warm - lists the parent directory, populating the index; null when
* the key has no distinct parent to list.
*/
export async function entryOrWarm(index, virtualKey, warm) {
const parent = rstripSlash(virtualKey).replace(/\/[^/]+$/, '') || '/';
return indexLock(index, parent, async () => {
let listing = await index.listDir(parent, virtualKey);
if (listing.entries != null && !listing.entries.includes(virtualKey))
return null;
const hit = await index.get(virtualKey);
if (hit.entry != null &&
(listing.entries != null || listing.partialEntries?.includes(virtualKey) === true))
return hit.entry;
if (warm === null)
return null;
if (listing.status === LookupStatus.EXPIRED || (listing.entries != null && hit.entry == null)) {
// Retained metadata is not proof of existence. Drop the old children
// before warming, including when a best-effort listing only puts rows.
// A live listing that names the key with no row lost it to eviction,
// so it is listed again too.
await index.invalidateDir(parent);
}
if (hit.entry != null) {
// Put-only rows have no parent membership to remove. A missing or
// partial refresh must not leave the old target available to the retry.
await index.invalidatePrefix(virtualKey);
}
try {
await warm();
}
catch (err) {
if (!isEnoent(err))
throw err;
return null;
}
listing = await index.listDir(parent, virtualKey);
if (listing.entries != null && !listing.entries.includes(virtualKey))
return null;
const warmed = await index.get(virtualKey);
return warmed.entry ?? null;
});
}
//# sourceMappingURL=warm.js.map