2
votes

I'm creating a database transaction with several insertions inside it. Results are saving as array of Future. Then I'm looking for the operation results in do{..}.catch{..} construction. And here is the

issue: if I'm returning failed future from do block then all transaction is rolling back - good, but if I'm returning the same failed future from "catch" block then some records are committing to the database.

    func save(on req: Request) -> Future<Confirmation>
    {
      return req.transaction(on: .psql) { conn in
      let promise = conn.eventLoop.newPromise(Confirmation.self)
      var futures = [Future<Bool>]()
       for i in 0 ..< 20 
       {
         let g1 = Group()
         g1.name = "\(i)"
         let f1 = g1.save(on: conn).then { _ -> Future<Bool> in
         if i == 15
         {
//          return conn.eventLoop.newSucceededFuture(result: false) //1
            return conn.eventLoop.newFailedFuture(error: SyncError.nullPrimaryKey) // 2
          } 
          else 
          {
            return conn.eventLoop.newSucceededFuture(result: true)
          }
        }
        futures.append(f1)
      }

      futures.do(on: conn){ results in
        var res = true
        results.forEach { e in
          res = res && e
        }
        if res {
          promise.succeed(result: Confirmation())
        } 
        else {
          promise.fail(error: SyncError.nullPrimaryKey) // 3
         }
        }.catch { e in
         promise.fail(error: e) // 4
     }
     return promise.futureResult
    }
  }
}

In this example promise is fulfilled with failure in the line 4 (block catch), and I have the issue of not-reverted transaction. But if I comment out line 1 and uncomment line 2 then promise is fulfilled in line 3 (block do), and entire transaction is reverted correctly.

Is it my fault somewhere in code, or is it Fluent bug?

1

1 Answers

2
votes

I'm not sure about constructions in your example code and especially about SyncError.nullPrimaryKey error in if i == 15, but it looks like the code below doing the same

func save(_ req: Request) throws -> Future<Confirmation> {
    return req.transaction(on: .psql) { conn in
        return (0...15).map {
            Group(name: $0)
        }.map {
            $0.save(on: conn).transform(to: ())
        }.flatten(on: conn).transform(to: Confirmation())
    }
}

Hope it helps