防止同时执行任务
Prevent from executing tasks in same time
我需要有关如何在我的应用程序中处理 oauth2 令牌刷新的建议。
我正在使用 GRPC 向我的 API 发出 http 请求,我使用 oauth2 令牌(它在 1 小时后过期)连接。
在启动每个请求之前,我检查令牌:
最新?启动网络请求
过时了?启动 refreshToken -> 启动 networkRequest
似乎一切正常,但在某些情况下,我的客户 "lose" 令牌。
问题是对于 2 个请求 A 和 B 在完全相同的时间 发起 ,如果令牌已过时,它们都会刷新它。
我的服务器会生成一个newTokenA,return它,生成newTokenB(去掉newTokenA),return它。
如果响应 newTokenA 在 newTokenB 之后到达客户端 ,则客户端令牌令牌将不是好的令牌。
我使用了Semaphore来确保同时调用refreshToken。
但是当我的信号量正在等待时,我没有收到来自服务器的任何响应。
let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0)
func authenticate(completion: (GRPCProtoCall) -> (Void)) -> GRPCProtoCall {
// Wait here if authenticate already called
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
// If token up to date
if isOAuth2TokenValid() {
dispatch_semaphore_signal(semaphore) // Release semaphore
completion(self.withAuthorization())
return self
}
// Refresh the outdated token
APIClient.shared.oAuth2AccessTokenRefresh { (response) -> (Void) in
dispatch_semaphore_signal(semaphore) // Release semaphore
completion(self.withAuthorization())
}
return self
}
首先,我建议为 1
资源创建信号量,而不是为 0
(用于阅读目的)创建信号量:
let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0)
其次,我认为问题是你先释放信号量,然后调用完成块:做这样的事情:
// Refresh the outdated token
APIClient.shared.oAuth2AccessTokenRefresh { (response) -> (Void) in
completion(self.withAuthorization())
dispatch_semaphore_signal(semaphore) // Release semaphore at very end
}
我认为你的 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
持有你的线程,你可以尝试超时以防最后一个请求没有响应,并将其放在 return self
之前
while semaphore.wait(timeout: DispatchTime.now() + Double(5000000000) / Double(NSEC_PER_SEC)) == DispatchTimeoutResult.success {//time out set to 5 seconds
print("wait")
}
为什么不使该方法完全异步? (self
反正好像知道)
func authenticate(completion: (GRPCProtoCall) -> ()) {
// If token up to date
if isOAuth2TokenValid() {
completion(self.withAuthorization())
} else {
// Refresh the outdated token
APIClient.shared.oAuth2AccessTokenRefresh { response in
completion(self.withAuthorization())
}
}
}
我需要有关如何在我的应用程序中处理 oauth2 令牌刷新的建议。
我正在使用 GRPC 向我的 API 发出 http 请求,我使用 oauth2 令牌(它在 1 小时后过期)连接。
在启动每个请求之前,我检查令牌:
最新?启动网络请求
过时了?启动 refreshToken -> 启动 networkRequest
似乎一切正常,但在某些情况下,我的客户 "lose" 令牌。
问题是对于 2 个请求 A 和 B 在完全相同的时间 发起 ,如果令牌已过时,它们都会刷新它。 我的服务器会生成一个newTokenA,return它,生成newTokenB(去掉newTokenA),return它。 如果响应 newTokenA 在 newTokenB 之后到达客户端 ,则客户端令牌令牌将不是好的令牌。
我使用了Semaphore来确保同时调用refreshToken。
但是当我的信号量正在等待时,我没有收到来自服务器的任何响应。
let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0)
func authenticate(completion: (GRPCProtoCall) -> (Void)) -> GRPCProtoCall {
// Wait here if authenticate already called
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
// If token up to date
if isOAuth2TokenValid() {
dispatch_semaphore_signal(semaphore) // Release semaphore
completion(self.withAuthorization())
return self
}
// Refresh the outdated token
APIClient.shared.oAuth2AccessTokenRefresh { (response) -> (Void) in
dispatch_semaphore_signal(semaphore) // Release semaphore
completion(self.withAuthorization())
}
return self
}
首先,我建议为 1
资源创建信号量,而不是为 0
(用于阅读目的)创建信号量:
let semaphore: dispatch_semaphore_t = dispatch_semaphore_create(0)
其次,我认为问题是你先释放信号量,然后调用完成块:做这样的事情:
// Refresh the outdated token
APIClient.shared.oAuth2AccessTokenRefresh { (response) -> (Void) in
completion(self.withAuthorization())
dispatch_semaphore_signal(semaphore) // Release semaphore at very end
}
我认为你的 dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
持有你的线程,你可以尝试超时以防最后一个请求没有响应,并将其放在 return self
while semaphore.wait(timeout: DispatchTime.now() + Double(5000000000) / Double(NSEC_PER_SEC)) == DispatchTimeoutResult.success {//time out set to 5 seconds
print("wait")
}
为什么不使该方法完全异步? (self
反正好像知道)
func authenticate(completion: (GRPCProtoCall) -> ()) {
// If token up to date
if isOAuth2TokenValid() {
completion(self.withAuthorization())
} else {
// Refresh the outdated token
APIClient.shared.oAuth2AccessTokenRefresh { response in
completion(self.withAuthorization())
}
}
}