-
Improvement
-
Resolution: Unresolved
-
Minor
-
None
-
4.5
-
MOODLE_405_STABLE
-
MDL-82652-main
-
-
-
Team Dragons 2025 Sprint 1.2, Team Dragons 2025 Sprint 1.3
REST does not, on the whole, suppor the notion of bulk actions.
Endpoints are typically in the format:
- GET /resourcetype[s] -> Get all instances
- POST /resourcetype -> Create a new instance
- GET /resourcetype/:instanceid -> Get an instance
- DELETE /resourcetype/:instanceid -> Delete that instance
- PATCH /resourcetype/:instanceid -> Update part of that instance
- PUT /resourcetype/:instanceid -> Update that instance
None of these allow for bulk actions (except for the GET all) and the RESTful design does not accomodate for these.
There are a number of approaches that can be taken to this:
- Use of a batch endpoint
- Use of many batch endpoints
- Accepting parameters to the base endpoint without any instanceid
Use of a batch endpoint
This is a technique that both Microsoft and Google employ.
The idea here is that a new, generic, endpoint is created at a root level, for example in the case of sharepoint it may be:
https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/make-batch-requests-with-the-rest-apis
This endpoint accepts a POST method and a request body with MIME type of multipart/mixed. The body contains a number of requests, each in its own part, and each defining the relevant HTTP verb and REST url and any parameters and/or body.
Example content may look like this:
POST https://fabrikam.sharepoint.com/_api/$batch HTTP/1.1
|
Authorization: Bearer <access token omitted>
|
Content-Type: multipart/mixed; boundary=batch_e3b6819b-13c3-43bb-85b2-24b14122fed1
|
Host: fabrikam.sharepoint.com
|
Content-Length: 527
|
Expect: 100-continue
|
|
--batch_e3b6819b-13c3-43bb-85b2-24b14122fed1
|
Content-Type: application/http
|
Content-Transfer-Encoding: binary
|
|
GET https://fabrikam.sharepoint.com/_api/Web/lists/getbytitle('Composed%20Looks')/items?$select=Title HTTP/1.1
|
|
--batch_e3b6819b-13c3-43bb-85b2-24b14122fed1
|
Content-Type: application/http
|
Content-Transfer-Encoding: binary
|
|
GET https://fabrikam.sharepoint.com/_api/Web/lists/getbytitle('User%20Information%20List')/items?$select=Title HTTP/1.1
|
|
--batch_e3b6819b-13c3-43bb-85b2-24b14122fed1--
|
Any part of the REST URL on the same REST baseUrl may be used.
Requests are returned in the same order as the request.
Requests are non-transactional.
Any failing request will not impede any subsequent request.
Pros and Cons
- Not limited to a single endpoint
- Allows for many requests to be performed in a single request
- Depending on how we implement it this could have some caching issues (not sure)
- More complex implementation
- Implementation only done once for all web services
- Requires a matching server/client implementation (easy)
- Commonly used in other products
- Requests are actually still dealt with individually, and not as a whole
- Which means that each, for example, delete request is still processed individaully (e.g. DELETE FROM foo WHERE id = x vs a list of ids).
Sources
- Google API descrption of batch endpoints
- Google API Client for JavaScript
- MS SharePoint/O365 description
Multiple batch endpoints
Another approach to this problem is for each resource type to have its own batch endpoints, separate to the standard endpoints.
This is an approach taken by Zendesk and others.
Rather than having a single batch endpoint taking multipart data with one part per action, for example:
- https://
{subdomain}.zendesk.com/api/v2/organizations/update_many.json
* https://{subdomain}.zendesk.com/api/v2//update_many.json
In the case of zendesk, they queue an asynchronous job and return the jobid only.
The job status can be queried separately. This is an optional thing - we could implement this kind of queue but it is not a requirement.
The zendesk appraoch allows for different bulk actions on the same resource to be queued.
Pros and cons
- Each resource must write its own batch handler
- Queue handling can get messy if using async jobs
- Still individual CRUD operatons per action
- Simpler than the MS/Google batch approach in some ways
- Ideally has a matching client/server implementation to do properly, but is not strictly required
Sources
Individual endpoints
Another appraoch would be have the generic resource type accept a request body for bulk actions.
For example:
- POST /resourcetype
- DELETE /resourcetype
This is supported from OpenAPI 3.1 onwards (which we are using) but is currently marked as discouraged. There is more information on the GH ticket that approved this workflow as to the main reason for it being discouraged, notably:
- RFC7231 does not define explicit semantics for request bodies on DELETE
- Client-side caching can be thrown by this (normally the DELETE of a specific resource will invalidate this in a cache)
- lots of conjecture that something not explicitly defined is something that should generally be avoided
This can be done by specifying data in the query parameter, or header parameters, but these have their own drawbacks, including URI length
Pros and cons
- Not well supported
- Generally discouraged
- Allows for bulk deletion (fewer DB queries etc)
Sources
- https://github.com/OAI/OpenAPI-Specification/issues/1801
- https://stackoverflow.com/questions/54939681/swagger-openapi-spec-3-0-delete-operation
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE
Summary
Generally speaking there is no good approach to this issue. Every approach has its drawbacks.
Personally I'm inclined to suggest that the single batch approach with a batching client gives the most flexibility, but is also hardest to implement well.
The simplest to implement is the individual bulk endpoints but these have the most repitition too.
Sources
- https://stackoverflow.com/questions/21863326/delete-multiple-records-using-rest
- https://www.codementor.io/blog/batch-endpoints-6olbjay1hd
- https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/make-batch-requests-with-the-rest-apis
- https://developerblog.zendesk.com/from-100-requests-to-1-introducing-our-new-bulk-and-batch-apis-a5bb294e2132
- https://developers.shopware.com/developers-guide/rest-api/examples/batch/
- https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/DELETE
- https://learn.microsoft.com/en-us/sharepoint/dev/sp-add-ins/make-batch-requests-with-the-rest-apis#code-samples
- https://developers.google.com/drive/api/guides/performance#batch-requests
- https://itnext.io/mass-delete-via-http-rest-how-do-you-do-it-1bff0f5eb72d
- https://stackoverflow.com/questions/54939681/swagger-openapi-spec-3-0-delete-operation
- https://github.com/OAI/OpenAPI-Specification/issues/1801