#Best Practices for Error Handling When Updating Bridge Table (Composite IDs)

15 messages · Page 1 of 1 (latest)

sweet ivy
#

What are the best practices when it comes to going about error handling for a function that is updating a bridge table?

Is it necessary to verify to check if the two records that comprises its composite ID (e.g., facilityUuid for the Facility model and workerUuid for the Worker model) before updating it? Or will it check for that on its own as a consequential result?

Here's are some snippet examples:

export function updateFacilityWorker(
  facilityUuid: FacilityWorker["facilityUuid"],
  workerUuid: Worker["uuid"],
  data: Omit<Prisma.FacilityWorkerUpdateInput, TimestampFields>
): Promise<UpdatedFacilityWorker> {
  return prisma.facilityWorker.update({
    select: {
      facilityUuid: true,
      workerUuid: true,
      rating: true,
      status: true,
    },
    where: {
      facility_worker_id: { facilityUuid, workerUuid },
    },
    data,
  });
}
model FacilityWorker {
    facilityUuid String               @db.Uuid
    facility     HealthCareFacility   @relation(fields: [facilityUuid], references: [uuid], onDelete: Cascade)

    workerUuid   String               @db.Uuid
    worker       Worker               @relation(fields: [workerUuid], references: [uuid], onDelete: Cascade)

    rating       Int?                 @db.SmallInt
    status       FacilityWorkerStatus @default(Available)

    @@id(fields: [facilityUuid, workerUuid], name: "facility_worker_id")
    @@index(fields: [facilityUuid, workerUuid, status], name: "worker_status_at_facility")
}
plucky phoenix
# sweet ivy What are the best practices when it comes to going about error handling for a fu...

Hi vmathi Tt is necessary to verify that the two records comprising its composite ID exist before updating the bridge table. This is to ensure data integrity and to avoid potential errors during the update process.

You can do it using something like that:

export async function updateFacilityWorker(
  facilityUuid: FacilityWorker["facilityUuid"],
  workerUuid: Worker["uuid"],
  data: Omit<Prisma.FacilityWorkerUpdateInput, TimestampFields>
): Promise<UpdatedFacilityWorker> {
  // Check if the facility and worker exist
  const facilityExists = await prisma.facility.findUnique({
    where: { uuid: facilityUuid },
  });

  const workerExists = await prisma.worker.findUnique({
    where: { uuid: workerUuid },
  });

  if (!facilityExists) {
    throw new Error(`Facility with UUID ${facilityUuid} does not exist.`);
  }

  if (!workerExists) {
    throw new Error(`Worker with UUID ${workerUuid} does not exist.`);
  }

  // Proceed with the update inside a transaction
  return prisma.$transaction(async (prisma) => {
    return prisma.facilityWorker.update({
      select: {
        facilityUuid: true,
        workerUuid: true,
        rating: true,
        status: true,
      },
      where: {
        facility_worker_id: { facilityUuid, workerUuid },
      },
      data,
    });
  });
}
sweet ivy
#

.
Also, I understand what $transaction does and what it is for, but why is it necessary within your code sample?

Wouldn't the first two checks render that transaction check unneeded? I thought it was just for use cases where you need to upsert multiple models/entities.

This isn't me questioning you. This is just me as a Prisma-noob who's seeking to better understand the $transaction feature in this particular use case.

plucky phoenix
# sweet ivy . Also, I understand what `$transaction` does and what it is for, but why is it ...

Wrapping the update in a transaction can ensure that all operations within the transaction scope either complete successfully or roll back together, which is crucial for maintaining database consistency, especially if the update operation depends on multiple steps or includes additional related changes.

Using a transaction ensures atomicity. If any part of the update process fails, the transaction will roll back, leaving the database in a consistent state. This is especially useful if there are multiple dependent operations or if future modifications might require additional steps within the update process.

sweet ivy
#

I guess the part I'm lost on is the fact that the first two first are both read operations that don't update anything that would both throw an error, terminating the flow of operations before reading the actual write operations.

Do the read/select queries effect the database in anyway that I'm not considering?

Or is it more of a just-in-case anything goes wrong with the actual update/write operation itself?

plucky phoenix
sweet ivy
#

Gotcha. Thanks. 🙂

sweet ivy
#

@plucky phoenix Is there a reason for it to be returning an array?

#

It seems to require an array of promises and not just a single promise.

#

Oh, wait. I see. It was released with 4.7.0 and this project is still using ^4.4.0.

sweet ivy
#

@plucky phoenix Last question: Do I need to confirm the existence of the FacilityWorker entity/record as well before attempting to update it? Or is that handled under the hood?

plucky phoenix
sweet ivy
#

Would it throw an error or will it just return nil?

plucky phoenix