Skip to content

Instantly share code, notes, and snippets.

@cipolleschi
Last active June 2, 2020 10:11
Show Gist options
  • Select an option

  • Save cipolleschi/28a2e0426d501199529cb54b01f0022a to your computer and use it in GitHub Desktop.

Select an option

Save cipolleschi/28a2e0426d501199529cb54b01f0022a to your computer and use it in GitHub Desktop.
/// 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