Files
drop/server/internal/objects/transactional.ts
DecDuck 251ddb8ff8 Rearchitecture for v0.4.0 (#197)
* feat: database redist support

* feat: rearchitecture of database schemas, migration reset, and #180

* feat: import redists

* fix: giantbomb logging bug

* feat: partial user platform support + statusMessage -> message

* feat: add user platform filters to store view

* fix: sanitize svg uploads

... copilot suggested this

I feel dirty.

* feat: beginnings of platform & redist management

* feat: add server side redist patching

* fix: update drop-base commit

* feat: import of custom platforms & file extensions

* fix: redelete platform

* fix: remove platform

* feat: uninstall commands, new R UI

* checkpoint: before migrating to nuxt v4

* update to nuxt 4

* fix: fixes for Nuxt v4 update

* fix: remaining type issues

* feat: initial feedback to import other kinds of versions

* working commit

* fix: lint

* feat: redist import
2025-11-10 10:36:13 +11:00

73 lines
2.2 KiB
TypeScript

/*
The purpose of this class is to hold references to remote objects (like images) until they're actually needed
This is used as a utility in metadata handling, so we only fetch the objects if we're actually creating a database record.
*/
import type { Readable } from "stream";
import { randomUUID } from "node:crypto";
import objectHandler from ".";
import type { TaskRunContext } from "../tasks/utils";
export type TransactionDataType = string | Readable | Buffer;
type TransactionTable = Map<string, TransactionDataType>; // ID to data
type GlobalTransactionRecord = Map<string, TransactionTable>; // Transaction ID to table
export type Register = (url: TransactionDataType) => string;
export type Pull = () => Promise<void>;
export type Dump = () => void;
export class ObjectTransactionalHandler {
private record: GlobalTransactionRecord = new Map();
new(
metadata: { [key: string]: string },
permissions: Array<string>,
context?: TaskRunContext,
): [Register, Pull, Dump] {
const transactionId = randomUUID();
this.record.set(transactionId, new Map());
const register = (data: TransactionDataType) => {
const objectId = randomUUID();
this.record.get(transactionId)?.set(objectId, data);
return objectId;
};
const pull = async () => {
const transaction = this.record.get(transactionId);
if (!transaction) return;
let progress = 0;
const increment = 100 / transaction.size;
for (const [id, data] of transaction) {
if (typeof data === "string") {
context?.logger.info(`Importing object from "${data}"`);
} else {
context?.logger.info(`Importing raw object...`);
}
await objectHandler.createFromSource(
id,
() => {
if (typeof data === "string") {
return $fetch<Readable>(data, { responseType: "stream" });
}
return (async () => data)();
},
metadata,
permissions,
);
progress += increment;
context?.progress(progress);
}
};
const dump = () => {
this.record.delete(transactionId);
};
return [register, pull, dump];
}
}