You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
With Async, it's idiomatic to chain methods. However, in methods that create new Futures (such as Fluent's Model.save()), any previous errors thrown seem to be discarded. This means calls to Abort() will not always abort the request.
Details
It's highly desirable to be able to do something like the following:
return tryUser.query(on: req).filter(\User.username == userReq.id).count().makeSureCountIsZero().saveUser(userRequest: userReq, on: req)
Where makeSureCountIsZero throws if count != 0, and saveUser is like this (simplified for clarity):
extensionFuturewhere T ==Bool{func saveUser(userRequest:UserRequest, on connectable:Request)throws->Future<User>{letnewUser=User(username: name)return newUser.save(on: connectable)}}
However, Model.save() is creating a brand new Future, which I believe is discarding any previous exceptions/errors on the previous Future.
Simplified Example
In TodoController.swift:
extensionFuturewhere T ==String{func returnString()throws->Future<String>{returnFuture("✨ everything is perfect ✨")}}finalclassTodoController{func getThrow(_ req:Request)throws->Future<String>{returntryTodo.query(on: req).filter(\Todo.title =="title").count().map(to:String.self){ _ inthrowAbort(.badRequest, reason:"Everything is not perfect")}.returnString()}}
Calling the getThrow method should return a 400, but instead we get a 200 OK and successful response from returnString
Unpack and build (may require 2018-01-30 toolchain)
Run and request GET /throw
Workarounds / Regression
I think the correct thing to do is actually to flatMap the future before returning a new future, as in the following, which does throw the Abort correctly.
extensionFuturewhere T ==String{func returnString()throws->Future<String>{returnself.flatMap(to:String.self){ _ inreturnFuture("✨ everything is perfect ✨")}}}
However, many users will not realize this, and their errors will be silently caught and ignored. Obviously that could be extremely dangerous. I'm hoping there's a way to force the error to be bubbled up. If there isn't, hopefully there's a way to catch this user error at compile time.
The text was updated successfully, but these errors were encountered:
Summary
With Async, it's idiomatic to chain methods. However, in methods that create new Futures (such as Fluent's
Model.save()
), any previous errors thrown seem to be discarded. This means calls toAbort()
will not always abort the request.Details
It's highly desirable to be able to do something like the following:
Where
makeSureCountIsZero
throws ifcount != 0
, andsaveUser
is like this (simplified for clarity):However,
Model.save()
is creating a brand new Future, which I believe is discarding any previous exceptions/errors on the previous Future.Simplified Example
In
TodoController.swift
:Calling the
getThrow
method should return a 400, but instead we get a 200 OK and successful response fromreturnString
Steps to Reproduce
2018-01-30
toolchain)GET /throw
Workarounds / Regression
I think the correct thing to do is actually to
flatMap
the future before returning a new future, as in the following, which doesthrow
the Abort correctly.However, many users will not realize this, and their errors will be silently caught and ignored. Obviously that could be extremely dangerous. I'm hoping there's a way to force the error to be bubbled up. If there isn't, hopefully there's a way to catch this user error at compile time.
The text was updated successfully, but these errors were encountered: