no message

This commit is contained in:
Peter 2015-07-16 18:27:59 +03:00
parent f74a350697
commit 95e2d53dd9
2 changed files with 89 additions and 45 deletions

View File

@ -2,25 +2,27 @@ import Foundation
import SwiftSignalKit
public final class Postbox {
static let PeerTagGeneral = 0
public class Modifier<State: Coding> {
private unowned var postbox: Postbox<State>
public class Modifier {
private unowned var postbox: Postbox
private init(postbox: Postbox) {
self.postbox = postbox
}
public func addMessages(messages: [Message], medias: [Media]) {
self.postbox.addMessages(messages, medias: medias)
}
public func deleteMessagesWithIds(ids: [MessageId]) {
self.postbox.deleteMessagesWithIds(ids)
}
private init(postbox: Postbox<State>) {
self.postbox = postbox
}
public func addMessages(messages: [Message], medias: [Media]) {
self.postbox.addMessages(messages, medias: medias)
}
public func deleteMessagesWithIds(ids: [MessageId]) {
self.postbox.deleteMessagesWithIds(ids)
}
public func setState(state: Coding) {
self.postbox.setState(state)
}
}
public final class Postbox<State: Coding> {
private let basePath: String
private let messageNamespaces: [MessageId.Namespace]
@ -29,6 +31,7 @@ public final class Postbox {
private var peerMessageViews: [PeerId : Bag<(MutableMessageView, Pipe<MessageView>)>] = [:]
private var peerViews: Bag<(MutablePeerView, Pipe<PeerView>)> = Bag()
private var statePipe: Pipe<State> = Pipe()
public init(basePath: String, messageNamespaces: [MessageId.Namespace]) {
self.basePath = basePath
@ -53,7 +56,7 @@ public final class Postbox {
private func createSchema() {
//state
self.database.execute("CREATE TABLE state (data BLOB)")
self.database.execute("CREATE TABLE state (id INTEGER, data BLOB)")
//peer_messages
self.database.execute("CREATE TABLE peer_messages (peerId INTEGER, namespace INTEGER, id INTEGER, data BLOB, associatedMediaIds BLOB, timestamp INTEGER, PRIMARY KEY(peerId, namespace, id))")
@ -311,6 +314,34 @@ public final class Postbox {
return ids
}
private func setState(state: Coding) {
let encoder = Encoder()
encoder.encodeRootObject(state)
let blob = Blob(data: encoder.makeData())
self.database.prepareCached("INSERT OR REPLACE INTO state (id, data) VALUES (?, ?)").run(Int64(0), blob)
}
public func state() -> Signal<State, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.queue.dispatch {
for row in self.database.prepareCached("SELECT data FROM state WHERE id = ?").run(Int64(0)) {
let data = (row[0] as! Blob).data
let buffer = ReadBuffer(memory: UnsafeMutablePointer(data.bytes), length: data.length, freeWhenDone: false)
let decoder = Decoder(buffer: buffer)
if let state = decoder.decodeRootObject() as? State {
subscriber.putNext(state)
}
break
}
disposable.set(self.statePipe.signal().start(next: { next in
subscriber.putNext(next)
}))
}
return disposable
}
}
private func addMessages(messages: [Message], medias: [Media]) {
let messageInsertStatement = self.database.prepare("INSERT INTO peer_messages (peerId, namespace, id, data, associatedMediaIds, timestamp) VALUES (?, ?, ?, ?, ?, ?)")
let peerMediaInsertStatement = self.database.prepare("INSERT INTO peer_media (peerId, mediaNamespace, messageNamespace, messageId) VALUES (?, ?, ?, ?)")
@ -596,7 +627,6 @@ public final class Postbox {
}
}
for (namespace, messageIds) in messageIdsByNamespace {
var queryString = "DELETE FROM peer_messages WHERE peerId = ? AND namespace = ? AND id IN ("
var first = true
@ -671,11 +701,17 @@ public final class Postbox {
}
}
public func modify(f: Modifier -> Void) {
self.queue.dispatch {
self.database.transaction()
f(Modifier(postbox: self))
self.database.commit()
public func modify<T>(f: Modifier<State> -> T) -> Signal<T, NoError> {
return Signal { subscriber in
self.queue.dispatch {
self.database.transaction()
let result = f(Modifier(postbox: self))
self.database.commit()
subscriber.putNext(result)
subscriber.putCompletion()
}
return EmptyDisposable
}
}

View File

@ -93,6 +93,14 @@ class TestMedia: Media {
}
}
class EmptyState: Coding {
required init(decoder: Decoder) {
}
func encode(encoder: Encoder) {
}
}
class PostboxTests: XCTestCase {
override func setUp() {
@ -113,8 +121,8 @@ class PostboxTests: XCTestCase {
let basePath = "/tmp/postboxtest"
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
let postbox = Postbox(basePath: basePath, messageNamespaces: [messageNamespace])
postbox.modify { state in
let postbox = Postbox<EmptyState>(basePath: basePath, messageNamespaces: [messageNamespace])
(postbox.modify { state -> Void in
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
for i in 0 ..< 10 {
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
@ -122,27 +130,27 @@ class PostboxTests: XCTestCase {
state.addMessages([message, message], medias: [testMedia])
}
return
}
}).start()
postbox._dumpTables()
postbox.modify { state in
(postbox.modify { state -> Void in
var messageIds: [MessageId] = []
for i in 0 ..< 5 {
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
messageIds.append(messageId)
}
state.deleteMessagesWithIds(messageIds)
}
}).start()
postbox._dumpTables();
postbox.modify { state in
(postbox.modify { state -> Void in
var messageIds: [MessageId] = []
for i in 0 ..< 10 {
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
messageIds.append(messageId)
}
state.deleteMessagesWithIds(messageIds)
}
}).start()
postbox._dumpTables();
}
@ -602,9 +610,9 @@ class PostboxTests: XCTestCase {
let basePath = "/tmp/postboxtest"
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
let postbox = Postbox(basePath: basePath, messageNamespaces: [messageNamespace])
let postbox = Postbox<EmptyState>(basePath: basePath, messageNamespaces: [messageNamespace])
postbox.modify { state in
(postbox.modify { state -> Void in
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
for i in 0 ..< 10 {
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
@ -612,13 +620,13 @@ class PostboxTests: XCTestCase {
state.addMessages([message, message], medias: [testMedia])
}
return
}
}).start()
postbox.tailMessageViewForPeerId(otherId, count: 4).start(next: { next in
println(next)
})
postbox.modify { state in
(postbox.modify { state -> Void in
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
for i in 10 ..< 15 {
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
@ -626,7 +634,7 @@ class PostboxTests: XCTestCase {
state.addMessages([message, message], medias: [testMedia])
}
return
}
}).start()
postbox._sync()
}
@ -642,9 +650,9 @@ class PostboxTests: XCTestCase {
let basePath = "/tmp/postboxtest"
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
let postbox = Postbox(basePath: basePath, messageNamespaces: [messageNamespaceCloud, messageNamespaceLocal])
let postbox = Postbox<EmptyState>(basePath: basePath, messageNamespaces: [messageNamespaceCloud, messageNamespaceLocal])
postbox.modify { state in
(postbox.modify { state -> Void in
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
for i in 0 ..< 10 {
let messageId = MessageId(peerId: otherId, namespace: messageNamespaceCloud, id: Int32(i + 1))
@ -657,14 +665,14 @@ class PostboxTests: XCTestCase {
state.addMessages([message, message], medias: [testMedia])
}
return
}
}).start()
var i = 1000
postbox.aroundMessageViewForPeerId(otherId, id: MessageId(peerId: otherId, namespace: messageNamespaceCloud, id: Int32(i + 1)), count: 3).start(next: { next in
println(next)
})
postbox.modify { state in
(postbox.modify { state -> Void in
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
for i in 10 ..< 15 {
let messageId = MessageId(peerId: otherId, namespace: messageNamespaceCloud, id: Int32(i + 1))
@ -672,7 +680,7 @@ class PostboxTests: XCTestCase {
state.addMessages([message, message], medias: [testMedia])
}
return
}
}).start()
postbox._sync()
}
@ -783,9 +791,9 @@ class PostboxTests: XCTestCase {
let basePath = "/tmp/postboxtest"
NSFileManager.defaultManager().removeItemAtPath(basePath, error: nil)
let postbox = Postbox(basePath: basePath, messageNamespaces: [messageNamespace])
let postbox = Postbox<EmptyState>(basePath: basePath, messageNamespaces: [messageNamespace])
postbox.modify { state in
(postbox.modify { state -> Void in
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
for i in 0 ..< 10 {
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
@ -793,7 +801,7 @@ class PostboxTests: XCTestCase {
state.addMessages([message, message], medias: [testMedia])
}
return
}
}).start()
postbox.tailPeerView(3).start(next: { next in
println(next)
@ -803,7 +811,7 @@ class PostboxTests: XCTestCase {
println(next)
})
postbox.modify { state in
(postbox.modify { state -> Void in
let testMedia = TestMedia(id: MediaId(namespace: TestMediaNamespace.Test.rawValue, id: 1))
for i in 10 ..< 15 {
let messageId = MessageId(peerId: otherId, namespace: messageNamespace, id: Int32(i + 1))
@ -811,7 +819,7 @@ class PostboxTests: XCTestCase {
state.addMessages([message, message], medias: [testMedia])
}
return
}
}).start()
postbox._sync()
}