@0xtim I suppose this is how you can wrap the database inserts in a transaction that can be rolled back in the event one of the futures fails and throws. The code below assumes a PostgreSQL database and a response of HTTPStatus type:
struct AcronymsController: RouteCollection {
func boot(router: Router) throws {
...
let tokenAuthMiddleware = User.tokenAuthMiddleware()
let guardAuthMiddleware = User.guardAuthMiddleware()
let tokenAuthGroup = acronymsRoutes.grouped(tokenAuthMiddleware, guardAuthMiddleware)
tokenAuthGroup.post(AcronymCreateData.self, use: createHandler)
tokenAuthGroup.post([AcronymCreateData].self, use: createAcronymsHandler)
...
}
func createAcronymsHandler(_ req: Request, acronymsData: [AcronymCreateData]) throws -> Future<HTTPStatus> {
let user = try req.requireAuthenticated(User.self)
var acronymSaveResults: [Future<Acronym>] = []
return req.transaction(on: .psql) { conn in
for acronymData in acronymsData {
let acronym = try Acronym(short: acronymData.short, long: acronymData.long, userID: user.requireID())
acronymSaveResults.append(acronym.save(on: conn))
}
return acronymSaveResults.flatten(on: conn)
.transform(to: .created)
}
}
...
}
struct AcronymCreateData: Content {
let short: String
let long: String
}