refactor(api): extract allocation assignment mutation effects

This commit is contained in:
2026-03-31 22:21:30 +02:00
parent 59690b86ac
commit dbf5401910
2 changed files with 116 additions and 78 deletions
@@ -0,0 +1,79 @@
import {
emitAllocationCreated,
emitAllocationDeleted,
emitAllocationUpdated,
} from "../sse/event-bus.js";
import {
checkBudgetThresholdsInBackground,
dispatchAllocationWebhookInBackground,
invalidateDashboardCacheInBackground,
} from "./allocation-effects.js";
type AllocationMutationDb = Parameters<typeof checkBudgetThresholdsInBackground>[0];
type AllocationMutationPayload = {
id: string;
projectId: string;
resourceId: string | null;
};
export function publishAllocationCreated(
db: AllocationMutationDb,
payload: AllocationMutationPayload,
options?: { dispatchWebhook?: boolean },
) {
emitAllocationCreated(payload);
if (options?.dispatchWebhook) {
dispatchAllocationWebhookInBackground(db, "allocation.created", payload);
}
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(db, payload.projectId);
}
export function publishAllocationUpdated(
db: AllocationMutationDb,
payload: AllocationMutationPayload & { resourceIds?: string[] },
options?: { dispatchWebhook?: boolean },
) {
emitAllocationUpdated(payload);
if (options?.dispatchWebhook) {
dispatchAllocationWebhookInBackground(db, "allocation.updated", payload);
}
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(db, payload.projectId);
}
export function publishAllocationDeleted(
db: AllocationMutationDb,
payload: AllocationMutationPayload,
) {
emitAllocationDeleted(payload.id, payload.projectId, payload.resourceId);
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(db, payload.projectId);
}
export function publishBatchAllocationDeletes(
db: AllocationMutationDb,
payloads: AllocationMutationPayload[],
) {
for (const payload of payloads) {
emitAllocationDeleted(payload.id, payload.projectId, payload.resourceId);
}
invalidateDashboardCacheInBackground();
for (const projectId of new Set(payloads.map((payload) => payload.projectId))) {
checkBudgetThresholdsInBackground(db, projectId);
}
}
export function publishBatchAllocationStatusUpdates(
db: AllocationMutationDb,
payloads: AllocationMutationPayload[],
) {
for (const payload of payloads) {
emitAllocationUpdated(payload);
}
invalidateDashboardCacheInBackground();
for (const projectId of new Set(payloads.map((payload) => payload.projectId))) {
checkBudgetThresholdsInBackground(db, projectId);
}
}
@@ -20,15 +20,12 @@ import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { findUniqueOrThrow } from "../db/helpers.js";
import {
emitAllocationCreated,
emitAllocationDeleted,
emitAllocationUpdated,
} from "../sse/event-bus.js";
import {
checkBudgetThresholdsInBackground,
dispatchAllocationWebhookInBackground,
invalidateDashboardCacheInBackground,
} from "./allocation-effects.js";
publishAllocationCreated,
publishAllocationDeleted,
publishAllocationUpdated,
publishBatchAllocationDeletes,
publishBatchAllocationStatusUpdates,
} from "./allocation-assignment-effects.js";
import {
ASSIGNMENT_INCLUDE,
toIsoDate,
@@ -94,18 +91,11 @@ export const allocationAssignmentProcedures = {
}).allocations[0]!;
});
emitAllocationCreated({
publishAllocationCreated(ctx.db, {
id: allocation.id,
projectId: allocation.projectId,
resourceId: allocation.resourceId,
});
dispatchAllocationWebhookInBackground(ctx.db, "allocation.created", {
id: allocation.id,
projectId: allocation.projectId,
resourceId: allocation.resourceId,
});
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(ctx.db, allocation.projectId);
}, { dispatchWebhook: true });
return allocation;
}),
@@ -121,13 +111,11 @@ export const allocationAssignmentProcedures = {
);
});
emitAllocationCreated({
publishAllocationCreated(ctx.db, {
id: assignment.id,
projectId: assignment.projectId,
resourceId: assignment.resourceId,
});
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(ctx.db, assignment.projectId);
return assignment;
}),
@@ -184,18 +172,11 @@ export const allocationAssignmentProcedures = {
},
));
emitAllocationUpdated({
publishAllocationUpdated(ctx.db, {
id: updated.id,
projectId: updated.projectId,
resourceId: updated.resourceId,
});
dispatchAllocationWebhookInBackground(ctx.db, "allocation.updated", {
id: updated.id,
projectId: updated.projectId,
resourceId: updated.resourceId,
});
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(ctx.db, updated.projectId);
}, { dispatchWebhook: true });
return { assignment: updated, action: "reactivated" as const };
}
@@ -215,13 +196,11 @@ export const allocationAssignmentProcedures = {
},
));
emitAllocationCreated({
publishAllocationCreated(ctx.db, {
id: assignment.id,
projectId: assignment.projectId,
resourceId: assignment.resourceId,
});
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(ctx.db, assignment.projectId);
return { assignment, action: "created" as const };
}),
@@ -246,19 +225,12 @@ export const allocationAssignmentProcedures = {
);
});
emitAllocationUpdated({
publishAllocationUpdated(ctx.db, {
id: updated.id,
projectId: updated.projectId,
resourceId: updated.resourceId,
resourceIds: [existing.resourceId, updated.resourceId],
});
dispatchAllocationWebhookInBackground(ctx.db, "allocation.updated", {
id: updated.id,
projectId: updated.projectId,
resourceId: updated.resourceId,
});
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(ctx.db, updated.projectId);
}, { dispatchWebhook: true });
return updated;
}),
@@ -296,14 +268,13 @@ export const allocationAssignmentProcedures = {
return updatedAllocation;
});
emitAllocationUpdated({
publishAllocationUpdated(ctx.db, {
id: updated.id,
projectId: updated.projectId,
resourceId: updated.resourceId,
resourceIds: [existing.entry.resourceId, updated.resourceId],
resourceIds: [existing.entry.resourceId, updated.resourceId]
.filter((resourceId): resourceId is string => Boolean(resourceId)),
});
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(ctx.db, updated.projectId);
return updated;
}),
@@ -337,9 +308,11 @@ export const allocationAssignmentProcedures = {
});
});
emitAllocationDeleted(existing.id, existing.projectId, existing.resourceId);
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(ctx.db, existing.projectId);
publishAllocationDeleted(ctx.db, {
id: existing.id,
projectId: existing.projectId,
resourceId: existing.resourceId,
});
return { success: true };
}),
@@ -366,9 +339,11 @@ export const allocationAssignmentProcedures = {
});
});
emitAllocationDeleted(existing.entry.id, existing.projectId, existing.entry.resourceId);
invalidateDashboardCacheInBackground();
checkBudgetThresholdsInBackground(ctx.db, existing.projectId);
publishAllocationDeleted(ctx.db, {
id: existing.entry.id,
projectId: existing.projectId,
resourceId: existing.entry.resourceId,
});
return { success: true };
}),
@@ -403,19 +378,11 @@ export const allocationAssignmentProcedures = {
});
});
for (const allocation of existing) {
emitAllocationDeleted(
allocation.entry.id,
allocation.projectId,
allocation.entry.resourceId,
);
}
invalidateDashboardCacheInBackground();
const affectedProjectIds = [...new Set(existing.map((allocation) => allocation.projectId))];
for (const projectId of affectedProjectIds) {
checkBudgetThresholdsInBackground(ctx.db, projectId);
}
publishBatchAllocationDeletes(ctx.db, existing.map((allocation) => ({
id: allocation.entry.id,
projectId: allocation.projectId,
resourceId: allocation.entry.resourceId,
})));
return { count: existing.length };
}),
@@ -457,19 +424,11 @@ export const allocationAssignmentProcedures = {
},
});
for (const allocation of updated) {
emitAllocationUpdated({
id: allocation.id,
projectId: allocation.projectId,
resourceId: allocation.resourceId,
});
}
invalidateDashboardCacheInBackground();
const affectedProjectIds = [...new Set(updated.map((allocation) => allocation.projectId))];
for (const projectId of affectedProjectIds) {
checkBudgetThresholdsInBackground(ctx.db, projectId);
}
publishBatchAllocationStatusUpdates(ctx.db, updated.map((allocation) => ({
id: allocation.id,
projectId: allocation.projectId,
resourceId: allocation.resourceId,
})));
return { count: updated.length };
}),