Skip to content

d-exclaimation/desolate

Repository files navigation

Desolate

A scalable concurrency toolkit for Swift 5.5+

WARNING: Deprecated and no longer maintained

Desolate is a toolkit for Swift 5.5+ Actors and Concurrency capabilities. The library provide structures to model Swift Actors using Desolate that maintains its isolation while allowing both synchronous and asynchronous code to interface with the actors.

Documentation

Usages/Examples

Simple concurrent safe store showing the maintained isolation even when actor is given messages from a main synchronous task

import Desolate

enum StoreEvent: CustomStringConvertible {
    case update(key: String, item: String)
    case store(item: String, ref: Receiver<String>)
    case add(item: String)
    case get(key: String, ref: Receiver<String?>)
    case getAll(ref: Receiver<[String]>)
    case delete(key: String)

    var description: String {
        switch self {
        case .update(key: let key, item: let item):
            return "PUT/PATCH: \(key) -> \"\(item)\""
        case .store(item: let item, ref: _):
            return "POST: \"\(item)\""
        case .add(item: let item):
            return "POST: \"\(item)\""    
        case .get(key: let key, ref: _):
            return "GET: \(key)"
        case .getAll(ref: _):
            return "GET: *"
        case .delete(key: let key):
            return "DELETE: \(key)"
        }
    }
}

actor Store: AbstractDesolate, NonStop {
    private var storage: [String: (String, Date)] = [:]

    public func onMessage(msg: StoreEvent) async -> Signal {
        print("Received: \(msg)")

        switch msg {
        case .update(let key, let item):
            storage[key] = (item, Date())

        case .store(let item, let ref):
            let key = UUID().uuidString
            storage[key] = (item, Date())
            ref.tell(with: key)

        case .get(let key, let ref):
            ref.tell(with: storage[key]?.0)

        case .getAll(let ref):
            ref.tell(with: storage.values.sorted { $0.1 <= $1.1 } .map{ $0.0 })

        case .delete(let key):
            storage.removeValue(forKey: key)
        }

        return same
    }
}

let desolate = Desolate(of: Store())

desolate.tell(with: .add(item: "Hello")) // Passing message to Actor while maintaining actor-isolation

Feedback

If you have any feedback, feel free to reach out through the issues tab or through my Twitter @d_exclaimation.