Remove placement worker — buildS3Key already embeds prefix--filename for AMPP workflow

This commit is contained in:
Claude 2026-05-02 11:29:32 -04:00
parent 9ec0f91848
commit a32329abb2
2 changed files with 4 additions and 38 deletions

View file

@ -1225,7 +1225,6 @@ async function uploadFilePresigned(item, idx) {
setFileStatus(idx, 'uploading', 'Getting URL\u2026'); setFileStatus(idx, 'uploading', 'Getting URL\u2026');
const pre = await api('POST', '/api/presigned', { const pre = await api('POST', '/api/presigned', {
filename: item.name, prefix: selectedPrefix, contentType: mime, size: item.file.size, filename: item.name, prefix: selectedPrefix, contentType: mime, size: item.file.size,
amppFolderName: selectedPrefix,
}); });
if (!pre.success) throw new Error(pre.error || 'Failed to get presigned URL'); if (!pre.success) throw new Error(pre.error || 'Failed to get presigned URL');
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -1240,7 +1239,7 @@ async function uploadFilePresigned(item, idx) {
}); });
xhr.addEventListener('load', async () => { xhr.addEventListener('load', async () => {
if (xhr.status >= 200 && xhr.status < 300) { if (xhr.status >= 200 && xhr.status < 300) {
try { await api('POST', '/api/presigned/complete', { key: pre.key, size: item.file.size, filename: item.name, amppFolderName: selectedPrefix }); } catch(_) {} try { await api('POST', '/api/presigned/complete', { key: pre.key, size: item.file.size, filename: item.name }); } catch(_) {}
resolve({ key: pre.key }); resolve({ key: pre.key });
} else { } else {
reject(new Error(`S3 returned ${xhr.status}: ${xhr.statusText}`)); reject(new Error(`S3 returned ${xhr.status}: ${xhr.statusText}`));
@ -1315,7 +1314,7 @@ async function uploadFilePresigned(item, idx) {
setFileStatus(idx, 'uploading', '100%'); setFileStatus(idx, 'uploading', '100%');
// Notify server for quota tracking + queue AMPP placement // Notify server for quota tracking + queue AMPP placement
try { await api('POST', '/api/presigned/complete', { key, size: item.file.size, filename: item.name, amppFolderName: selectedPrefix }); } catch(_) {} try { await api('POST', '/api/presigned/complete', { key, size: item.file.size, filename: item.name }); } catch(_) {}
return { key }; return { key };
} }

View file

@ -11,8 +11,6 @@ const fs = require("fs");
const https = require("https"); const https = require("https");
const http = require("http"); const http = require("http");
const archiver = require("archiver"); const archiver = require("archiver");
const { placeAsset, placeAssetInFolderById, listAmppFolders } = require("./lib/ampp-folder-placer");
const AmppPlacementWorker = require("./lib/ampp-placement-worker");
require("events").defaultMaxListeners = 50; require("events").defaultMaxListeners = 50;
@ -79,7 +77,6 @@ function loadData() {
// Migrate existing data to include new fields if missing // Migrate existing data to include new fields if missing
function migrateData(data) { function migrateData(data) {
if (!data.shareLinks) data.shareLinks = []; if (!data.shareLinks) data.shareLinks = [];
if (!data.pendingPlacements) data.pendingPlacements = [];
for (const u of data.users) { for (const u of data.users) {
if (u.quotaMB === undefined) u.quotaMB = 0; if (u.quotaMB === undefined) u.quotaMB = 0;
if (!u.allowedFolders) u.allowedFolders = []; if (!u.allowedFolders) u.allowedFolders = [];
@ -140,19 +137,6 @@ function initS3() {
initS3(); initS3();
// ==================== AMPP PLACEMENT WORKER ====================
const placementWorker = new AmppPlacementWorker({
getAmppBase: getAmppBase,
getAmppToken: getAmppToken,
db,
saveData,
});
// Worker starts after first AMPP config check (deferred to avoid startup errors
// when AMPP is not yet configured).
function maybeStartWorker() {
if (getAmppApiKey() && !placementWorker._timer) placementWorker.start(30_000);
}
setTimeout(maybeStartWorker, 5000); // give server time to fully init
// Upload with timeout // Upload with timeout
function withTimeout(promise, ms, label) { function withTimeout(promise, ms, label) {
@ -589,7 +573,7 @@ app.post("/api/upload", requireAuth, upload.array("files", 50), async (req, res)
// Server only generates the signed URL and tracks quota/permissions. // Server only generates the signed URL and tracks quota/permissions.
app.post("/api/presigned", requireAuth, async (req, res) => { app.post("/api/presigned", requireAuth, async (req, res) => {
if (!s3Client) return res.status(503).json({ success: false, error: "S3 not configured" }); if (!s3Client) return res.status(503).json({ success: false, error: "S3 not configured" });
const { filename, prefix, contentType, size, amppFolderId, amppFolderName } = req.body; const { filename, prefix, contentType, size } = req.body;
if (!filename) return res.status(400).json({ success: false, error: "filename required" }); if (!filename) return res.status(400).json({ success: false, error: "filename required" });
if (isBlockedFile(filename)) return res.status(400).json({ success: false, error: `Blocked file type: ${filename}` }); if (isBlockedFile(filename)) return res.status(400).json({ success: false, error: `Blocked file type: ${filename}` });
@ -618,24 +602,12 @@ app.post("/api/presigned", requireAuth, async (req, res) => {
// Called by client after a successful direct-to-S3 upload to update quota + record AMPP placement // Called by client after a successful direct-to-S3 upload to update quota + record AMPP placement
app.post("/api/presigned/complete", requireAuth, (req, res) => { app.post("/api/presigned/complete", requireAuth, (req, res) => {
const { key, size, amppFolderId, amppFolderName, filename } = req.body; const { key, size } = req.body;
const user = db.users.find(u => u.username === req.sessionData.user); const user = db.users.find(u => u.username === req.sessionData.user);
if (user && size) { if (user && size) {
user.uploadedBytes = (user.uploadedBytes || 0) + size; user.uploadedBytes = (user.uploadedBytes || 0) + size;
saveData(db); saveData(db);
} }
// Record AMPP placement if a folder was selected
if ((amppFolderId || amppFolderName) && filename) {
if (!db.pendingPlacements) db.pendingPlacements = [];
db.pendingPlacements.push({
id: require("crypto").randomBytes(8).toString("hex"),
filename, s3Key: key, amppFolderId, amppFolderName: amppFolderName || amppFolderId,
status: "waiting", createdAt: new Date().toISOString(),
});
saveData(db);
maybeStartWorker();
console.log(`[presigned] Queued AMPP placement: ${filename} → folder ${amppFolderName}`);
}
console.log(`[presigned] Completed: ${key} (${size} bytes) by ${req.sessionData.user}`); console.log(`[presigned] Completed: ${key} (${size} bytes) by ${req.sessionData.user}`);
res.json({ success: true }); res.json({ success: true });
}); });
@ -850,11 +822,6 @@ app.get("/api/ampp/folders/list", requireAuth, async (req, res) => {
} }
}); });
// ---- Pending Placements Status ----
app.get("/api/ampp/placements", requireAuth, (req, res) => {
const placements = (db.pendingPlacements || []);
res.json({ success: true, placements });
});
// ---- AMPP Folder Placement ---- // ---- AMPP Folder Placement ----
// POST /api/ampp/place — place an already-ingested AMPP asset into virtual folders. // POST /api/ampp/place — place an already-ingested AMPP asset into virtual folders.