Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift Vapor:如何协调多个请求,直到完成一个中心请求_Swift_Vapor - Fatal编程技术网

Swift Vapor:如何协调多个请求,直到完成一个中心请求

Swift Vapor:如何协调多个请求,直到完成一个中心请求,swift,vapor,Swift,Vapor,我有一个中间件,如果在Redis中找不到令牌,它会获取令牌 struct令牌中间件:中间件,令牌访问器{ func respond(to request:request,chainingTo next:Responder)抛出->未来{ guard let=request.http.headers.firstValue(名称:HTTPHeaderName(“客户端ID”))else{ 抛出中止(.badRequest,原因:“标头中缺少“客户端ID”) } guard request.clien

我有一个中间件,如果在Redis中找不到令牌,它会获取令牌

struct令牌中间件:中间件,令牌访问器{
func respond(to request:request,chainingTo next:Responder)抛出->未来{
guard let=request.http.headers.firstValue(名称:HTTPHeaderName(“客户端ID”))else{
抛出中止(.badRequest,原因:“标头中缺少“客户端ID”)
}
guard request.clientID.isEmpty==false else{
抛出中止(.badRequest,原因:“'Client-ID'在标头中为空”)
}
guard let=request.http.headers.firstValue(名称:HTTPHeaderName(“客户机机密”))else{
抛出中止(.badRequest,原因:“标头中缺少“客户端机密”)
}
///getToken获取一个新令牌并将其存储在Redis中供控制器使用
返回try self.getToken(请求:request).flatMap(to:Response.self){token in
返回并重试下一步。响应(至:请求)
}
}
}
扩展令牌中间件:服务{}
但这会导致多个进程自己获取新令牌,因此会出现竞争条件


在vapor中如何处理这个问题?

我现在解决了这个问题,多亏了Soroush,他向我暗示了正确的方向。有关DispatchQueues的更多信息,请参阅

因此:

在服务器上的iOS和Vapor中,我们都可以创建一个
DispatchQueue
。在我的例子中,我使用的是并发的,在令牌读取、获取(如果需要)和令牌写入发生的关键部分,我使用了一个屏障

屏障只允许一个人进入,因此在这一部分中,一切都像串行队列一样执行

希望这能帮助任何可能遇到同样问题的人

导入蒸汽
协议令牌访问器:重新访问器{
}
扩展令牌存取器{
///主要方便功能,处理过期、重新蚀刻等
///
///-检查之前是否保存了令牌
///-我们将令牌存储在redis中
///-我们使用redis TTL功能处理令牌到期
///
func getToken(请求:请求)抛出->未来{
打印(“:getToken(请求:)”)
让promise=request.eventLoop.newPromise(Token.self)
返回请求。withNewConnection(到:.redis){redis in
让concurrentQueue=DispatchQueue(标签:“com.queuename.gettoken”,
属性:。并发)
///使并发队列串行,因为一次只允许一个队列获取新令牌
concurrentQueue.async(标志:。屏障){
让uz=redis.get(request.clientIdLastDigits,as:String.self).map(to:Void.self){tokenOpt-in
guard let accessToken=tokenOpt else{
尝试self.fetchNewToken(forRequest:request).do{newToken in
打印(“获取新令牌”)
承诺。成功(结果:纽顿)
}.catch{中的错误
打印(“获取新令牌失败”)
承诺失败(错误:错误)
}
返回
}
打印(“从redis获得有效令牌”)
let token=token(client:request.clientidlastdights,token:accessToken,expiresIn:Date())
//返回请求。未来(令牌)
承诺。成功(结果:令牌)
}
}
回报承诺。未来的结果
}
}
...
这是通过中间件在我的方法前面触发的(所以我不需要考虑它)

导入蒸汽
结构令牌中间件:中间件、令牌访问器{
func respond(to request:request,chainingTo next:Responder)抛出->未来{
guard let=request.http.headers.firstValue(名称:HTTPHeaderName(“客户端ID”))else{
抛出中止(.badRequest,原因:“标头中缺少“客户端ID”)
}
guard request.clientID.isEmpty==false else{
抛出中止(.badRequest,原因:“'Client-ID'在标头中为空”)
}
guard let=request.http.headers.firstValue(名称:HTTPHeaderName(“客户机机密”))else{
抛出中止(.badRequest,原因:“标头中缺少“客户端机密”)
}
返回try self.getToken(请求:request).flatMap(to:Response.self){token in
返回并重试下一步。响应(至:请求)
}
}
}
扩展令牌中间件:服务{}