swagger-api / swagger-api/swagger-codegen

[Swift] Alamofire client template does not support concurrent request

Open
#9,321 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Mustache
Stars
17.8k
Forks
6k
PR merge metrics
No merged PRs in 30d

Description

Description

The current Alamofire client template implementation does not support concurrent requests. The static AlamofireRequestBuilder.execute method adds an instance of Alamofire.SessionManager to a global variable (managerStore) without any thread safe mechanism to avoid concurrent accesses. Therefore this can result, for example, in the deallocation of a Alamofire.SessionManager that might cancel the request. As result, the requests affect will return Error Domain=NSURLErrorDomain Code=-999 "cancelled".

Swagger-codegen version

2.3.1, 3.0.5

Swagger declaration file content or url

Not needed, all applications making concurrent requests using the Alamofire implementation of these version should experience the same issues.

Command line used for generation

swagger-codegen-2.3.1 generate -i http://localhost:8083/api-docs/v1/swagger.json -l swift4 -o swagger-client

Steps to reproduce

Dispatch several concurrent operation to a OperationQueue performing different API requests. Check if any of these calls resulted in a cancelled request.

Suggest a fix/enhancement

I can think about two different solutions that could help in the resolution of this problem:

  • Instead of using static methods, relying on global variables/state and create on each request a new session manager, we could instead use an API Client instance that would be injected/kept in memory and configurable as needed.
  • Make the global variable thread safe. We could use something like this:
public final class Synchronized<T> {
    
    private let queue: DispatchQueue
    private var _value: T
    
    public init(_ value: T) {
        let queueLabel = "com.codegen.synchronized.\(type(of: value)).\(UUID().uuidString)"
        self.queue = DispatchQueue(label: queueLabel, attributes: .concurrent)
        self._value = value
    }
    
    public var value: T {
        var result: T? = nil
        queue.sync { result = self._value }
        return result!
    }
    
    public func write(using block: @escaping (inout T) -> Void) {
        queue.async(flags: .barrier) {
            block(&self._value)
        }
    }
}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the AlamofireRequestBuilder.execute entry point and inspect how managerStore holds Alamofire.SessionManager instances. Reproduce the problem by dispatching several requests through an OperationQueue, then verify that concurrent requests complete without cancellation and add or update coverage if the relevant template tests are found.

Written by the indexing model from the issue text.

Assessment

Tech stack
swift
Domain
api, mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.