fix(GRO-643): add appointment indexes to schema and S3 error handling (#315)
- Add idx_appointments_client_id, idx_appointments_staff_id, idx_appointments_start_time, idx_appointments_status to schema. Migration 0029 already handles the DB side; this brings schema.ts in sync so drizzle-kit push is clean going forward. - Wrap deleteObject calls in try/catch (POST /photo/confirm and DELETE /:petId/photo endpoints) so S3 failures don't abort the DB update — orphaned objects are logged as warnings instead. Co-authored-by: Test User <test@example.com> Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit was merged in pull request #315.
This commit is contained in:
committed by
GitHub
parent
2577e33c50
commit
772f4df62f
@@ -213,7 +213,11 @@ petsRouter.post(
|
|||||||
|
|
||||||
// Delete the previous photo from storage to avoid orphaned objects
|
// Delete the previous photo from storage to avoid orphaned objects
|
||||||
if (pet.photoKey) {
|
if (pet.photoKey) {
|
||||||
|
try {
|
||||||
await deleteObject(pet.photoKey);
|
await deleteObject(pet.photoKey);
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(`Failed to delete previous photo ${pet.photoKey}, orphaned object may remain:`, err);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const [row] = await db
|
const [row] = await db
|
||||||
@@ -240,7 +244,11 @@ petsRouter.delete("/:petId/photo", async (c) => {
|
|||||||
if (!pet) return c.json({ error: "Pet not found" }, 404);
|
if (!pet) return c.json({ error: "Pet not found" }, 404);
|
||||||
if (!pet.photoKey) return c.json({ error: "No photo on file" }, 404);
|
if (!pet.photoKey) return c.json({ error: "No photo on file" }, 404);
|
||||||
|
|
||||||
|
try {
|
||||||
await deleteObject(pet.photoKey);
|
await deleteObject(pet.photoKey);
|
||||||
|
} catch (err) {
|
||||||
|
console.warn(`Failed to delete photo ${pet.photoKey} from S3, orphaned object may remain:`, err);
|
||||||
|
}
|
||||||
await db
|
await db
|
||||||
.update(pets)
|
.update(pets)
|
||||||
.set({ photoKey: null, photoUploadedAt: null, updatedAt: new Date() })
|
.set({ photoKey: null, photoUploadedAt: null, updatedAt: new Date() })
|
||||||
|
|||||||
@@ -200,7 +200,9 @@ export const appointmentGroups = pgTable("appointment_groups", {
|
|||||||
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const appointments = pgTable("appointments", {
|
export const appointments = pgTable(
|
||||||
|
"appointments",
|
||||||
|
{
|
||||||
id: uuid("id").primaryKey().defaultRandom(),
|
id: uuid("id").primaryKey().defaultRandom(),
|
||||||
clientId: uuid("client_id")
|
clientId: uuid("client_id")
|
||||||
.notNull()
|
.notNull()
|
||||||
@@ -244,7 +246,14 @@ export const appointments = pgTable("appointments", {
|
|||||||
customerNotes: text("customer_notes"),
|
customerNotes: text("customer_notes"),
|
||||||
createdAt: timestamp("created_at").notNull().defaultNow(),
|
createdAt: timestamp("created_at").notNull().defaultNow(),
|
||||||
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
updatedAt: timestamp("updated_at").notNull().defaultNow(),
|
||||||
});
|
},
|
||||||
|
(t) => [
|
||||||
|
index("idx_appointments_client_id").on(t.clientId),
|
||||||
|
index("idx_appointments_staff_id").on(t.staffId),
|
||||||
|
index("idx_appointments_start_time").on(t.startTime),
|
||||||
|
index("idx_appointments_status").on(t.status),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
export const invoices = pgTable(
|
export const invoices = pgTable(
|
||||||
"invoices",
|
"invoices",
|
||||||
|
|||||||
Reference in New Issue
Block a user