Desolate

Prototype actor and async/await toolkit for Swift 5.5+

import Desolate

enum StoreEvent: CustomStringConvertible {
    case update(key: String, item: String)
    case store(item: String, ref: RecipientRef<String>)
    case add(item: String)
    case get(key: String, ref: RecipientRef<String?>)
    case getAll(ref: RecipientRef<[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 {
    public var status: Signal = .running

    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 .running
    }
}

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.

GitHub

View Github