Synchronous or asynchronous in swift server (Perfect)

580 views Asked by At

I have created a Swift 3.0 server using the Perfect Framework. Everything works great as expected but i am trying to learn if there is a better way to do some things.

Coming from an iOS background I know to always call any blocking function in a different thread. Does this still hold when developing in the server?

For example, if I have a long blocking task (like making another request or performing a large database query), does it make a difference to call it synchronously:

routes.add(method: .get, uri: "/", handler: { request, response in
    longSynchronousTask()
    response.appendBody(string: "Finished")
    response.completed()
})

or should I be doing this asynchronously?

routes.add(method: .get, uri: "/", handler: { request, response in
    longAsynchronousTask(completion: {
        response.appendBody(string: "Finished")
        response.completed()
    })
})
2

There are 2 answers

0
Jochen Bedersdorfer On

Depends on the framework. I wasn't able to find more information about perfect.org's architecture but since it claims to run on a "high-performance asynchronous networking engine", the expectation is that a thread handling a request is not supposed to block.

Most reactive frameworks (like Node.js, Vert.x) rely on one or multiple event threads that are handling requests. If these threads block, no more requests can be handled!

Which means that longer running tasks should be run in their own threads. There are frameworks that provide a mechanism for that (like worker-threads).

The question then becomes: What is a longer running task? if your task does I/O in an asynchronous fashion and merely 'waits' for I/O, you can do that on the event thread.

If you do lengthy computation, you might be better off putting that into a separate thread.

0
user3639488 On

yes, you can. I use the following code test, it's OK.

struct DBOperationQueue {
    static let messageOperationQueue:OperationQueue = {
        let operationQueue = OperationQueue()
        operationQueue.maxConcurrentOperationCount = 5
        return operationQueue
    }()
}

func handler(request: HTTPRequest, response: HTTPResponse) {
    DBOperationQueue.messageOperationQueue.addOperation {

        sleep(10)

        print("sleep complete")

        response.setHeader(.contentType, value: "text/html")
        response.appendBody(string: "<html><title>Hello, world!</title><body>Hello, world!</body></html>")
        response.completed()
    }
}