feat: preview and retry sync jobs
This commit is contained in:
@@ -38,6 +38,8 @@ export async function POST(req: Request, { params }: { params: Promise<{ id: str
|
||||
const name = identity.displayName || identity.nickname || identity.username || identity.name;
|
||||
db.prepare("UPDATE sources SET name=?,last_connection_at=CURRENT_TIMESTAMP,last_connection_error=NULL,remote_display_name=?,remote_avatar_url=? WHERE id=?").run(name, name, avatarUrl, id);
|
||||
} catch (connectionError) { const message = connectionError instanceof Error ? connectionError.message : "Connection failed"; db.prepare("UPDATE sources SET last_connection_error=? WHERE id=?").run(message, id); throw connectionError; }
|
||||
} else if (action === "retry-failed-jobs") {
|
||||
if (!owner) throw new Error("Only the owner can retry all failed jobs"); db.prepare("UPDATE sync_jobs SET status='queued',attempts=0,last_error=NULL,started_at=NULL,finished_at=NULL,run_after=CURRENT_TIMESTAMP WHERE source_id=? AND status='failed'").run(id);
|
||||
} else if (action === "leave") {
|
||||
if (owner) throw new Error("Transfer ownership or delete the source before leaving");
|
||||
db.prepare("DELETE FROM source_members WHERE source_id=? AND user_id=?").run(id, user.id);
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { requireUser } from "@/lib/auth";
|
||||
import { decrypt } from "@/lib/crypto";
|
||||
import { db } from "@/lib/db";
|
||||
import { getMemosIdentity, listMemos } from "@/lib/memos";
|
||||
export async function GET(_request: Request, { params }: { params: Promise<{ id: string }> }) { try { const user = await requireUser(); const { id: rawId } = await params; const id = Number(rawId); const source = db.prepare("SELECT s.* FROM sources s JOIN source_members sm ON sm.source_id=s.id WHERE s.id=? AND sm.user_id=? AND s.integration_type='memos'").get(id, user.id) as any; if (!source) return NextResponse.json({ error: "Not found" }, { status: 404 }); const token = decrypt(source.token_encrypted); const identity = await getMemosIdentity(source.base_url, token); const rules = { creator: identity.name, tags: JSON.parse(source.sync_tags_json || "[]"), from: source.sync_from, to: source.sync_to, attachmentMode: source.sync_attachment_mode }; const remote = await listMemos(source.base_url, token, rules, { pageSize: 100 }); const local = new Set((db.prepare("SELECT remote_memo_name FROM posts WHERE source_id=? AND origin='memos'").all(id) as { remote_memo_name: string }[]).map((row) => row.remote_memo_name)); const added = remote.memos.filter((memo) => !local.has(memo.name)).length; return NextResponse.json({ inspected: remote.memos.length, added, existing: remote.memos.length - added, hasMore: Boolean(remote.nextPageToken) }); } catch (error) { return NextResponse.json({ error: error instanceof Error ? error.message : "preview" }, { status: 400 }); } }
|
||||
@@ -0,0 +1,6 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import { requireUser } from "@/lib/auth";
|
||||
import { db } from "@/lib/db";
|
||||
import { externalUrl } from "@/lib/http";
|
||||
import { requireSameOrigin } from "@/lib/security";
|
||||
export async function POST(request: Request, { params }: { params: Promise<{ id: string }> }) { try { requireSameOrigin(request); const user = await requireUser(); const { id: rawId } = await params; const id = Number(rawId); const job = db.prepare("SELECT j.id FROM sync_jobs j JOIN source_members sm ON sm.source_id=j.source_id WHERE j.id=? AND sm.user_id=? AND j.status='failed'").get(id, user.id); if (!job) throw new Error("Failed job not found"); db.prepare("UPDATE sync_jobs SET status='queued',attempts=0,last_error=NULL,started_at=NULL,finished_at=NULL,run_after=CURRENT_TIMESTAMP WHERE id=?").run(id); return NextResponse.redirect(externalUrl(request, "/dashboard?sync=queued")); } catch (error) { return NextResponse.redirect(externalUrl(request, "/dashboard?error=" + encodeURIComponent(error instanceof Error ? error.message : "retry"))); } }
|
||||
Reference in New Issue
Block a user