unibaraU
Convex Community2y ago
17 replies
unibara

Locking mechanism in custom Action (getOrCreate)?

When implementing an Action to getOrCreate a particular doc in a table, we'd like to make sure that the doc, which has a unique location_id column doesn't get created twice. However, we don't currently have a schema defined. Is there a way to handle the duplication of doc when this function is called in quick succession without defining a schema for all our tables and specifying the location_id column as unique?

We are using an action here because the create involves a 3rd party API request.

export const getOrCreate = action({
  args: {
    location_id: v.string(),
  },
  handler: async (ctx, { location_id }) => {
    const location: null | any = await ctx.runQuery(internal.locations.get, {
      location_id,
    });

    if (location) {
      return location;
    }
    const combinedObj = await fetchLocationWithPhotos(location_id);
    await ctx.runMutation(internal.locations.create, {
      combinedObj,
      location_id,
    });

    return {
      ...combinedObj,
      location_id,
    };
  },
});

export const get = internalQuery({
  args: {
    location_id: v.string(),
  },
  handler: async (ctx, { location_id }) => {
    return await ctx.db
      .query("locations")
      .filter((q) => q.eq(q.field("location_id"), location_id))
      .unique();
  },
});

export const create = internalMutation({
  args: {
    location_id: v.string(),
    combinedObj: v.any(),
  },
  handler: async (ctx, { location_id, combinedObj }) => {
    return await ctx.db.insert("locations", {
      location_id,
      ...combinedObj,
    });
  },
});
Was this page helpful?