Search code examples
swiftsiesta-swift

Siesta handling multiple requests


I have a loop where I POST requests to the server:

for (traineeId, points) in traineePointsDict {  
    // create a new point
    let parameters: NSDictionary = [
        "traineeId": "\(traineeId)",
        "numPoints": points,
        "exerciseId": "\(exerciseId)"
    ]

    DataManager.sharedInstance.api.points.request(.POST, json: parameters).success { data in
        if data.json["success"].int == 1 {
            self.pointCreated()
        } else {
            self.pointFailToCreate()
        }
    }.failure { error in
        self.pointFailToCreate()
    }
}

The problem is that for some reason the last request fails and I am guessing that this is due to posting too many requests to the server at the same time.

Is there a way to chain these requests so they wait for the one before to complete before executing the next?

I have been looking at PromiseKit, but I don't really know how to implement this and I am looking for a quick solution.


Solution

  • Siesta does not control how requests are queued or how many requests run concurrently. You have two choices:

    1. control it on the app side, or
    2. control it in the network layer.

    I’d investigate option 2 first. It gives you less fine-grained control, but it give you more robust options on the cheap and is less prone to mistakes. If you are using URLSession as your networking layer (which is Siesta’s default), then investigate whether the HTTPMaximumConnectionsPerHost property of URLSessionConfiguration does what you need. (Here are some examples of passing custom configuration to Siesta.)

    If that doesn’t work for you, a simple version of #1 is to use a completion handler to chain the requests:

    func chainRequests(_ queue: [ThingsToRequest])
      guard let thing = queue.first else { return }
      params = makeParamsFor(thing)
      resource.request(.POST, json: params)
        .onSuccess {
          ...
        }.onFailure {
          ...
        }.onCompletion { _ in
          chainRequests(queue[1 ..< queue.count])
        }
    }
    

    Note that you can attach multiple overlapping handlers to the same request, and they’re called in the order you attached them. Note also that Siesta guarantees that the completion block is always called, no matter the outcome. This means that each request will result in calls to either closures 1 & 3 or closures 2 & 3. That’s why this approach works.