Posting multiple items at once

@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
}
1 Like