Updating a database after an API service call

I’m looking to implement a service that takes in data, calls an API, then updates the database depending on that API call.

In the front end I would use a mutation to update that model, but how would I do it from the API side?

Use case would be this service being triggered by a button on the front-end, sending a GraphQL query to call the service and pass it the relevant data, and then await the API call before updating the database.

Hi Kuri,

Welcome to the community!

Your service function can contain any sort of logic you like, including making an external api call.

There’s an example here: Using a Third Party API | RedwoodJS Docs

Hope this helps!
Danny

Hi Danny!

Thanks for the welcome. Going off that example, I guess I’m trying to figure out if mutations are only used on the front-end, and under the API I would use something like

const updatedRecord = await db.table.update({
      where: { kw },
      data: {
        [key]: response.data[0]
      }
    }
    )

instead of importing an Apollo mutation, I guess?

I guess I’m trying to figure out if mutations are only used on the front-end

Yes, sort of!

The flow would be

  1. Mutation getSomeData {} . Make sure the mutation is defined in the relevant sdl file, so your API side knows how to handle it.
  2. This would invoke your resolver for your mutation in your service
export const getSomeData = () => {
const exeternalData = await fetch('https://api.bazinga.kittens')

return db.table.update({
// .... use your exeternal data here
})
}

Bonus:
If you want to be fancy, you can also make use of caching using Service Caching or GraphQL caching

1 Like

OK, that’s helpful!

My takeaway is that trying to call a mutation in a service would be an anti-pattern and I should instead interface with prisma on the API-side.

What about calling another service that can also interface with the front-end through GraphQL? Instead, would I just be importing that service and passing it data through a function call?

Example:

Let’s say I had a service that could book an appointment. Sometimes I use this through GraphQL queries sent from the front-end to book appointments.

I have a second service that reschedules appointments automatically, and within it has the logic for figuring out how to re-arrange appointments. I’d rather not duplicate the appointment-scheduling logic, so I have it call that first appointment-booking service. However this is from the back-end, so I’m not using GraphQL to call it and instead am just importing the schedule service?

Oh I understand what you were getting at.

Remember services are just functions. So If you can have your logic in one place, and reuse the logic from multiple services:

export const createAppointment = (input) => {
//... extra logic for creates only
const isValid = validateCreate(input)


return valid && _createOrUpdateAppointment({...})
}
}

export const reschedule = () => {
  // add any reschedule specific logic here
 // .....
 // then call the same function
  return _createOrUpdateAppointment(input)
}

// This is used internally by other mutation resolvers,
// and never invoked directly by GraphQL
const _createOrUpdateAppointment = (input) => {
return db.appointments.createOrUpdate(...}
} 

Only thing you need to watch out for, is to make sure the approriate security (i.e. @requireAuth("role") directive is applied in your SDLs for each of your mutations!

@danny - Oh, absolutely. I guess I’m wondering, do you reuse that logic via a GraphQL call if it’s API-to-API or from importing the function and passing it data directly?

Really appreciate your time on this, thank you!

To me it doesn’t make sense to call a GraphQL endpoint again from your service (unless it’s an external one). Just introduces network delay, because the request would go:

Browser → Server → Server → Browser

That extra step of the server calling itself feels a little off to me!

No worries, happy to help!

1 Like