DataAPI Mass Mutations - bettyblocks/cli GitHub Wiki

DataAPI Mass Mutations

Actions are great to CRUD application data in a workflow. But until now, you were only able to create records one by one if using our Actions IDE. This means that whenever you are importing 30K records they will be created separately and thus the DataAPI / database will be called 30K times.

Our DataAPI however does provide a createMany mutation (e.g. createManyArticle) but it was not possible to provide the input in a no-coders way. So the only solution was to write a very specific application function (with too much logic; hence bad practise and also quite the opposite of what we want to achieve as a platform) which executes the createMany mutation(s).

Helper function gql.buffer()

Enter the gql.buffer helper function which yields child steps and intercepts DataAPI create mutations (e.g. createArticle) within that scope and buffers it in memory and once all its child steps have finished executing it will "mass mutate" data.

In this case it executes a createManyArticle mutation (please note that at the time of writing we only intercept create mutations so all other GQL queries / mutations will hit the DataAPI / database still. Intercepting update mutations are coming up next.

Example

Our gql.buffer() function accepts two arguments:

  • an options object which the key steps which should be an asynchronous function that execute GQL create mutations indirectly (so basically the child steps)
  • a callback function that receives an array of objects of which the keys are the intercepted GQL mutations (e.g. createArticle) and as value an asynchronous function that does the actual createMany mutation (we left the responsibility to the pro-coder on to whether or not do the mass mutate)

Please note that the second argument has changed because we want to group the intercepted GQL mutations by "CUUD priority".

This is the enforced order:

  1. create
  2. update
  3. upsert
  4. delete
const massMutate = async (_, steps) => {
  const resolveMutationGroups = async (promise, mutations) => {
    await promise;
    return Promise.all(
      Object.entries(mutations).map(async ([, execute]) => execute()),
    );
  };

  await gql.buffer({ steps }, async (mutationGroups) => {
    await mutationGroups.reduce(resolveMutationGroups, Promise.resolve());
  });
};

export default massMutate;

See our Block Store massMutate (Block at MyBB and Github repo) function which does just that.