1 min read
Concurrency
Last Updated - Platform 23.0 - SDK 18.0The PoqSDK ensures that some core mechanism are thread-safe and provides a new API for asynchronous work based on the Swift Task
API.
Concurrent Mechanisms
With v23.0
the SDK aims to ensure that some core and commonly used mechanisms are thread-safe.
This avoids concurrency crashes that can be hard to track down.
It is completely possible to break this by replacing the default implementations with custom implementations. Sub-classing is preferred as these mechanisms should still provide concurrency.
Containers
Containers are concurrent using an internal recursive lock.
AppConfigs
Accessing the current app config via AppConfig.current
or AppConfigRepository
has concurrency built into the repository.
For advanced implementations it is better to subclass the PoqAppConfigService
rather than the repository.
Users
Accessing or modifying the user via User.current
or UserRepository
has concurrency and in-memory persistence built into the repository.
The PoqUserRepository
is open to sub-classing but only provides a small set of customisable functions.
Networking
The default NetworkSession
and Authenticator
implementations are concurrent.
Feature services use the task API which uses async / await under the hood. It is important to note that asnyc / await is not guaranteed to be concurrent but leads to better / robust concurrent code.
Tasks
The AsyncTask
API was introduced in v23.0
to replace all concurrent closure and delegate based operations and functions.
With the initial release they replace all PoqSDK service functions to return NetworkTask
types.
Unlike Swift Tasks, tasks do not execute immediately. Instead they evaluate when you execute them later. Tasks provide chainable SwiftUI style syntax similar to Combine publishers but can be executed in many ways:
- Using async / await via
await task.execute()
- Using closures via
task.execute { result in }
- Using Combine via
task.executePublisher()
This provides a solid foundation for future methods that are introduced to Swift and allows us to phase their roll out across the SDK continuing with closures.
Network tasks are an special typealias with additional convenience functions (read more here). But all tasks have convenience function for mapping or chaining tasks:
- Use
task.map
to map the successful output of a previous task. - Use
task.catch
to catch and map errors from the previous task. - Use
task.then
orthenOnMain
to perform an addition task after the previous completes.
This API will eventually be rolled out to repositories with the hope to providing asynchronous middleware.