Last active
June 2, 2020 10:11
-
-
Save cipolleschi/28a2e0426d501199529cb54b01f0022a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /// Protocol that defines the entities in our database. | |
| /// They must have an identifier that is used to retrieve them. | |
| protocol Entity { | |
| /// The identifier of the resource | |
| var id: String { get } | |
| } | |
| extension Entity { | |
| /// Helper to retrieve the table name from the Type of the entity. | |
| static var tableName: String { return String(reflecting: Self.self) } | |
| } | |
| /// Our in memory DB. It can store any object that conforms to Entity. | |
| class InMemoryDB { | |
| typealias Table = [String: Entity] | |
| /// The storage of our database. | |
| /// The key is a String obtained by the type using the `String(reflecting:)` API. | |
| private var storage: [String: Table] = [:] | |
| private var queue: OperationQueue | |
| init() { | |
| self.queue = OperationQueue() | |
| self.queue.name = "com.concurrency.app.in-memory-db" | |
| self.queue.maxConcurrentOperationCount = 1 | |
| } | |
| /// Retrieves the entity from the storage. | |
| func get<T: Entity>(for id: String, callback: @escaping (T?) -> Void) { | |
| // Adds an operation to the queue. | |
| self.queue.addOperation { | |
| let tableName = T.tableName | |
| let table = self.storage[tableName] | |
| let entity = table?[id] | |
| let typedEntity = entity as? T | |
| // Invokes the callback so the client can use the value. | |
| callback(typedEntity) | |
| } | |
| } | |
| /// Sets the entity into the storage, eventually creating a new table for it. | |
| func update<T: Entity>(for key: String, updateClosure: @escaping (T?) -> T?) { | |
| // Adds an operation to the queue. | |
| self.queue.addOperation { | |
| let tableName = T.tableName | |
| // Retrieves the entity from the table. | |
| var table: [String: Entity] = self.storage[tableName] ?? [:] | |
| let oldValue = self.storage[key] as? T | |
| // Runs the code that will update the value. | |
| let newValue = updateClosure(oldValue) | |
| // Sets the new value in the database. | |
| table[key] = newValue | |
| self.storage[tableName] = table | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment