Skip to content

Commit

Permalink
feat(swift5): add support for rate limit
Browse files Browse the repository at this point in the history
  • Loading branch information
ThibaultBee authored Apr 23, 2024
1 parent e6a124f commit 5df0045
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 69 deletions.
56 changes: 40 additions & 16 deletions Sources/APIs/AdvancedAuthenticationAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,26 @@ open class AdvancedAuthenticationAPI {
*/
@discardableResult
open class func authenticate(authenticatePayload: AuthenticatePayload, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping ((_ data: AccessToken?, _ error: Error?) -> Void)) -> RequestTask {
return authenticateWithRequestBuilder(authenticatePayload: authenticatePayload).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
return authenticate(authenticatePayload: authenticatePayload, apiResponseQueue: apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
}

/**
Get Bearer Token
- parameter authenticatePayload: (body)
- parameter apiResponseQueue: The queue on which api response is dispatched.
- parameter completion: completion handler to receive the result of the request (incl. headers).
*/
@discardableResult
open class func authenticate(authenticatePayload: AuthenticatePayload, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<AccessToken>, ErrorResponse>) -> Void) -> RequestTask {
return authenticateWithRequestBuilder(authenticatePayload: authenticatePayload).execute(apiResponseQueue, completion)
}


Expand All @@ -39,7 +51,7 @@ open class AdvancedAuthenticationAPI {
- parameter authenticatePayload: (body)
- returns: RequestBuilder<AccessToken>
*/
open class func authenticateWithRequestBuilder(authenticatePayload: AuthenticatePayload) -> RequestBuilder<AccessToken> {
internal class func authenticateWithRequestBuilder(authenticatePayload: AuthenticatePayload) -> RequestBuilder<AccessToken> {
let localVariablePath = "/auth/api-key"
let localVariableURLString = ApiVideoUploader.basePath + localVariablePath
let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: authenticatePayload)
Expand Down Expand Up @@ -67,14 +79,26 @@ open class AdvancedAuthenticationAPI {
*/
@discardableResult
open class func refresh(refreshTokenPayload: RefreshTokenPayload, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping ((_ data: AccessToken?, _ error: Error?) -> Void)) -> RequestTask {
return refreshWithRequestBuilder(refreshTokenPayload: refreshTokenPayload).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
return refresh(refreshTokenPayload: refreshTokenPayload, apiResponseQueue: apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
}

/**
Refresh Bearer Token
- parameter refreshTokenPayload: (body)
- parameter apiResponseQueue: The queue on which api response is dispatched.
- parameter completion: completion handler to receive the result of the request (incl. headers).
*/
@discardableResult
open class func refresh(refreshTokenPayload: RefreshTokenPayload, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<AccessToken>, ErrorResponse>) -> Void) -> RequestTask {
return refreshWithRequestBuilder(refreshTokenPayload: refreshTokenPayload).execute(apiResponseQueue, completion)
}


Expand All @@ -85,7 +109,7 @@ open class AdvancedAuthenticationAPI {
- parameter refreshTokenPayload: (body)
- returns: RequestBuilder<AccessToken>
*/
open class func refreshWithRequestBuilder(refreshTokenPayload: RefreshTokenPayload) -> RequestBuilder<AccessToken> {
internal class func refreshWithRequestBuilder(refreshTokenPayload: RefreshTokenPayload) -> RequestBuilder<AccessToken> {
let localVariablePath = "/auth/refresh"
let localVariableURLString = ApiVideoUploader.basePath + localVariablePath
let localVariableParameters = JSONEncodingHelper.encodingParameters(forEncodableObject: refreshTokenPayload)
Expand Down
106 changes: 80 additions & 26 deletions Sources/APIs/VideosAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,31 @@ open class VideosAPI {
*/
@discardableResult
open class func upload(videoId: String, file: URL, onProgressReady: ((Progress) -> Void)? = nil, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping ((_ data: Video?, _ error: Error?) -> Void)) throws -> RequestTask {
return try upload(videoId: videoId, file: file, onProgressReady: onProgressReady, apiResponseQueue: apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
}

/**
Upload a video
- parameter videoId: (path) Enter the videoId you want to use to upload your video.
- parameter file: (form) The path to the video you would like to upload. The path must be local. If you want to use a video from an online source, you must use the \\\&quot;/videos\\\&quot; endpoint and add the \\\&quot;source\\\&quot; parameter when you create a new video.
- parameter onProgressReady: progress handler to receive request progress.
- parameter apiResponseQueue: The queue on which api response is dispatched.
- parameter completion: completion handler to receive the result of the request (incl. headers).
*/
@discardableResult
open class func upload(videoId: String, file: URL, onProgressReady: ((Progress) -> Void)? = nil, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<Video>, ErrorResponse>) -> Void) throws -> RequestTask {
if (try file.isMultiChunk) {
return try UploadChunkRequestTaskQueue(videoId: videoId, file: file, onProgressReady: onProgressReady, apiResponseQueue: apiResponseQueue, completion: completion)
} else {
return uploadWithRequestBuilder(videoId: videoId, file: file, onProgressReady: onProgressReady).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
return uploadWithRequestBuilder(videoId: videoId, file: file, onProgressReady: onProgressReady).execute(apiResponseQueue, completion)
}
}

Expand Down Expand Up @@ -78,13 +92,25 @@ open class VideosAPI {
}

public func uploadPart(file: URL, partId: Int, isLastPart: Bool, onProgressReady: ((Progress) -> Void)? = nil, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping ((_ data: Video?, _ error: Error?) -> Void)) -> RequestTask {
let requestTask = uploadPart(file: file, partId: partId, isLastPart: isLastPart, onProgressReady: onProgressReady, completion: { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
})
return requestTask
}

public func uploadPart(file: URL, partId: Int, isLastPart: Bool, onProgressReady: ((Progress) -> Void)? = nil, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<Video>, ErrorResponse>) -> Void) -> RequestTask {
var numOfChunks: Int? = nil
if (isLastPart) {
numOfChunks = partId
}
let requestBuilder = uploadWithRequestBuilder(videoId: videoId, file: file, chunkId: partId, numOfChunks: numOfChunks, onProgressReady: onProgressReady)
execute(requestBuilder, apiResponseQueue: apiResponseQueue) { data, error in
completion(data, error)
execute(requestBuilder, apiResponseQueue: apiResponseQueue) { result in
completion(result)
}
return requestBuilder.requestTask
}
Expand Down Expand Up @@ -121,7 +147,7 @@ The latter allows you to split a video source into X chunks and send those chunk
- parameter onProgressReady: progress handler to receive request progress.
- returns: RequestBuilder<Video>
*/
open class func uploadWithRequestBuilder(videoId: String, file: URL, chunkId: Int? = nil, numOfChunks: Int? = nil, onProgressReady: ((Progress) -> Void)? = nil) -> RequestBuilder<Video> {
internal class func uploadWithRequestBuilder(videoId: String, file: URL, chunkId: Int? = nil, numOfChunks: Int? = nil, onProgressReady: ((Progress) -> Void)? = nil) -> RequestBuilder<Video> {
var localVariablePath = "/videos/{videoId}/source"
let videoIdPreEscape = "\(APIHelper.mapValueToPathItem(videoId))"
let videoIdPostEscape = videoIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
Expand Down Expand Up @@ -180,7 +206,7 @@ The latter allows you to split a video source into X chunks and send those chunk
- parameter onProgressReady: progress handler to receive request progress.
- returns: RequestBuilder<Video>
*/
open class func uploadWithRequestBuilder(videoId: String, file: FileChunkInputStream, chunkId: Int? = nil, numOfChunks: Int? = nil, onProgressReady: ((Progress) -> Void)? = nil) -> RequestBuilder<Video> {
internal class func uploadWithRequestBuilder(videoId: String, file: FileChunkInputStream, chunkId: Int? = nil, numOfChunks: Int? = nil, onProgressReady: ((Progress) -> Void)? = nil) -> RequestBuilder<Video> {
var localVariablePath = "/videos/{videoId}/source"
let videoIdPreEscape = "\(APIHelper.mapValueToPathItem(videoId))"
let videoIdPostEscape = videoIdPreEscape.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) ?? ""
Expand Down Expand Up @@ -220,17 +246,31 @@ The latter allows you to split a video source into X chunks and send those chunk
*/
@discardableResult
open class func uploadWithUploadToken(token: String, file: URL, videoId: String? = nil, onProgressReady: ((Progress) -> Void)? = nil, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping ((_ data: Video?, _ error: Error?) -> Void)) throws -> RequestTask {
return try uploadWithUploadToken(token: token, file: file, videoId: videoId, onProgressReady: onProgressReady, apiResponseQueue: apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
}

/**
Upload with an delegated upload token
- parameter token: (query) The unique identifier for the token you want to use to upload a video.
- parameter file: (form) The path to the video you want to upload.
- parameter onProgressReady: progress handler to receive request progress.
- parameter apiResponseQueue: The queue on which api response is dispatched.
- parameter completion: completion handler to receive the result of the request (incl. headers).
*/
@discardableResult
open class func uploadWithUploadToken(token: String, file: URL, videoId: String? = nil, onProgressReady: ((Progress) -> Void)? = nil, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<Video>, ErrorResponse>) -> Void) throws -> RequestTask {
if (try file.isMultiChunk) {
return try UploadChunkRequestTaskQueue(token: token, file: file, videoId: videoId, onProgressReady: onProgressReady, apiResponseQueue: apiResponseQueue, completion: completion)
} else {
return uploadWithUploadTokenWithRequestBuilder(token: token, file: file, videoId: videoId, onProgressReady: onProgressReady).execute(apiResponseQueue) { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
}
return uploadWithUploadTokenWithRequestBuilder(token: token, file: file, videoId: videoId, onProgressReady: onProgressReady).execute(apiResponseQueue, completion)
}
}

Expand Down Expand Up @@ -282,18 +322,32 @@ The latter allows you to split a video source into X chunks and send those chunk
}

public func uploadPart(file: URL, partId: Int, isLastPart: Bool, onProgressReady: ((Progress) -> Void)? = nil, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping ((_ data: Video?, _ error: Error?) -> Void)) -> RequestTask {
let requestTask = uploadPart(file: file, partId: partId, isLastPart: isLastPart, onProgressReady: onProgressReady, completion: { result in
switch result {
case let .success(response):
completion(response.body, nil)
case let .failure(error):
completion(nil, error)
}
})
return requestTask
}

public func uploadPart(file: URL, partId: Int, isLastPart: Bool, onProgressReady: ((Progress) -> Void)? = nil, apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue, completion: @escaping (_ result: Swift.Result<Response<Video>, ErrorResponse>) -> Void) -> RequestTask {
var numOfChunks: Int? = nil
if (isLastPart) {
numOfChunks = partId
}
let requestBuilder = uploadWithUploadTokenWithRequestBuilder(token: token, file: file, videoId: videoId, chunkId: partId, numOfChunks: numOfChunks, onProgressReady: onProgressReady)
execute(requestBuilder, apiResponseQueue: apiResponseQueue) { data, error in
if let data = data {
execute(requestBuilder, apiResponseQueue: apiResponseQueue) { result in
switch result {
case let .success(response):
if self.videoId == nil {
self.videoId = data.videoId
self.videoId = response.body.videoId
}
case .failure(_): break
}
completion(data, error)
completion(result)
}
return requestBuilder.requestTask
}
Expand Down Expand Up @@ -325,7 +379,7 @@ The latter allows you to split a video source into X chunks and send those chunk
- parameter onProgressReady: progress handler to receive request progress.
- returns: RequestBuilder<Video>
*/
open class func uploadWithUploadTokenWithRequestBuilder(token: String, file: URL, videoId: String? = nil, chunkId: Int? = nil, numOfChunks: Int? = nil, onProgressReady: ((Progress) -> Void)? = nil) -> RequestBuilder<Video> {
internal class func uploadWithUploadTokenWithRequestBuilder(token: String, file: URL, videoId: String? = nil, chunkId: Int? = nil, numOfChunks: Int? = nil, onProgressReady: ((Progress) -> Void)? = nil) -> RequestBuilder<Video> {
let localVariablePath = "/upload"
let localVariableURLString = ApiVideoUploader.basePath + localVariablePath
var localVariableFormParams: [String: Any?] = [
Expand Down Expand Up @@ -369,7 +423,7 @@ The latter allows you to split a video source into X chunks and send those chunk
- parameter onProgressReady: progress handler to receive request progress.
- returns: RequestBuilder<Video>
*/
open class func uploadWithUploadTokenWithRequestBuilder(token: String, file: FileChunkInputStream, videoId: String? = nil, chunkId: Int? = nil, numOfChunks: Int? = nil, onProgressReady: ((Progress) -> Void)? = nil) -> RequestBuilder<Video> {
internal class func uploadWithUploadTokenWithRequestBuilder(token: String, file: FileChunkInputStream, videoId: String? = nil, chunkId: Int? = nil, numOfChunks: Int? = nil, onProgressReady: ((Progress) -> Void)? = nil) -> RequestBuilder<Video> {
let localVariablePath = "/upload"
let localVariableURLString = ApiVideoUploader.basePath + localVariablePath
var localVariableFormParams: [String: Any?] = [
Expand Down
15 changes: 5 additions & 10 deletions Sources/Upload/RequestTaskQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ public class RequestTaskQueue<T>: RequestTask {
}

internal func execute(_ requestBuilder: RequestBuilder<T>,
apiResponseQueue: DispatchQueue = ApiVideoUploader.apiResponseQueue,
completion: @escaping (_ data: T?, _ error: Error?) -> Void) -> Void {
apiResponseQueue: DispatchQueue = ApiVideoClient.apiResponseQueue,
completion: @escaping (_ result: Swift.Result<Response<T>, ErrorResponse>) -> Void) -> Void {
requestBuilders.append(requestBuilder)
return operationQueue.addOperation(RequestOperation(requestBuilder: requestBuilder, apiResponseQueue: apiResponseQueue, willExecuteRequestBuilder: willExecuteRequestBuilder, completion: completion))
}
Expand All @@ -67,11 +67,11 @@ public class RequestTaskQueue<T>: RequestTask {
final class RequestOperation<T>: Operation {
private let requestBuilder: RequestBuilder<T>
private let apiResponseQueue: DispatchQueue
private let completion: (_ data: T?, _ error: Error?) -> Void
private let completion: (_ result: Swift.Result<Response<T>, ErrorResponse>) -> Void
private let willExecuteRequestBuilder: (_: RequestBuilder<T>) -> Void
private let group = DispatchGroup()

init(requestBuilder: RequestBuilder<T>, apiResponseQueue: DispatchQueue, willExecuteRequestBuilder: @escaping (_: RequestBuilder<T>) -> Void, completion: @escaping (_ data: T?, _ error: Error?) -> Void) {
init(requestBuilder: RequestBuilder<T>, apiResponseQueue: DispatchQueue, willExecuteRequestBuilder: @escaping (_: RequestBuilder<T>) -> Void, completion: @escaping (_ result: Swift.Result<Response<T>, ErrorResponse>) -> Void) {
self.requestBuilder = requestBuilder
self.apiResponseQueue = apiResponseQueue
self.willExecuteRequestBuilder = willExecuteRequestBuilder
Expand All @@ -87,12 +87,7 @@ final class RequestOperation<T>: Operation {

self.willExecuteRequestBuilder(requestBuilder)
requestBuilder.execute(apiResponseQueue) { result in
switch result {
case let .success(response):
self.completion(response.body, nil)
case let .failure(error):
self.completion(nil, error)
}
self.completion(result)
self.group.leave()
}
// Make task synchronous
Expand Down
Loading

0 comments on commit 5df0045

Please sign in to comment.