Skip to content
This repository has been archived by the owner on Feb 18, 2021. It is now read-only.

Updating for server compatibility with fixes for reply network messages #11

Merged
merged 5 commits into from
Nov 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions Jetstream.xcodeproj/xcshareddata/xcschemes/JetstreamTests.xcscheme
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "NO"
buildForArchiving = "NO"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7225560019F819DA0016D8F8"
BuildableName = "JetstreamTests.xctest"
BlueprintName = "JetstreamTests"
ReferencedContainer = "container:Jetstream.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
buildConfiguration = "Debug">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7225560019F819DA0016D8F8"
BuildableName = "JetstreamTests.xctest"
BlueprintName = "JetstreamTests"
ReferencedContainer = "container:Jetstream.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7225560019F819DA0016D8F8"
BuildableName = "JetstreamTests.xctest"
BlueprintName = "JetstreamTests"
ReferencedContainer = "container:Jetstream.xcodeproj">
</BuildableReference>
</MacroExpansion>
</TestAction>
<LaunchAction
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
buildConfiguration = "Debug"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7225560019F819DA0016D8F8"
BuildableName = "JetstreamTests.xctest"
BlueprintName = "JetstreamTests"
ReferencedContainer = "container:Jetstream.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
buildConfiguration = "Release"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "7225560019F819DA0016D8F8"
BuildableName = "JetstreamTests.xctest"
BlueprintName = "JetstreamTests"
ReferencedContainer = "container:Jetstream.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
11 changes: 5 additions & 6 deletions Jetstream/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,15 @@ public enum ClientStatus {

func receivedMessage(message: NetworkMessage) {
switch message {
case let sessionCreateResponse as SessionCreateReplyMessage:
case let sessionCreateReply as SessionCreateReplyMessage:
if session != nil {
logger.error("Received session create response with existing session")
} else if sessionCreateResponse.success == false {
logger.info("Denied starting session")
onSessionDenied.fire()
} else {
let token = sessionCreateResponse.sessionToken
} else if let token = sessionCreateReply.sessionToken {
logger.info("Starting session with token: \(token)")
session = Session(client: self, token: token)
} else {
logger.info("Denied starting session, error: \(sessionCreateReply.error)")
onSessionDenied.fire()
}
default:
session?.receivedMessage(message)
Expand Down
2 changes: 1 addition & 1 deletion Jetstream/ModelObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ struct PropertyInfo {
}

private var internalScope: Scope?
var scope: Scope? {
public internal(set) var scope: Scope? {
get {
return internalScope
}
Expand Down
4 changes: 4 additions & 0 deletions Jetstream/NetworkMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,14 @@ public class NetworkMessage {
return SessionCreateReplyMessage.unserialize(dictionary)
case SessionCreateReplyMessage.messageType:
return SessionCreateReplyMessage.unserialize(dictionary)
case ScopeFetchReplyMessage.messageType:
return ScopeFetchReplyMessage.unserialize(dictionary)
case ScopeStateMessage.messageType:
return ScopeStateMessage.unserialize(dictionary)
case ScopeSyncMessage.messageType:
return ScopeSyncMessage.unserialize(dictionary)
case ScopeSyncReplyMessage.messageType:
return ScopeSyncReplyMessage.unserialize(dictionary)
case PingMessage.messageType:
return PingMessage.unserialize(dictionary)
default:
Expand Down
17 changes: 13 additions & 4 deletions Jetstream/Scope.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,20 @@ import Signals
public var name: String

/// The root model associates with the scope
public var rootModel: ModelObject? {
if modelObjects.count > 0 {
return modelObjects[0]
public var root: ModelObject? {
get {
if modelObjects.count > 0 {
return modelObjects[0]
}
return nil
}
set {
if modelObjects.count == 0 {
if let definiteNewValue = newValue {
definiteNewValue.setScopeAndMakeRootModel(self)
}
}
}
return nil
}

var syncFragmentLookup = [NSUUID: SyncFragment]()
Expand Down
9 changes: 7 additions & 2 deletions Jetstream/ScopeFetchReplyMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class ScopeFetchReplyMessage: ReplyMessage {
let scopeIndex: UInt?
let error: NSError?

init(index: UInt, replyTo: UInt, scopeIndex: UInt?, error: NSError? = nil) {
init(index: UInt, replyTo: UInt, scopeIndex: UInt?, error: NSError?) {
self.scopeIndex = scopeIndex
self.error = error
super.init(index: index, replyTo: replyTo)
Expand All @@ -34,6 +34,7 @@ class ScopeFetchReplyMessage: ReplyMessage {
var index = dictionary["index"] as? UInt
var replyTo = dictionary["replyTo"] as? UInt
var scopeIndex = dictionary["scopeIndex"] as? UInt

var error: NSError?
if let serializedError = dictionary["error"] as? [String: AnyObject] {
error = errorFromDictionary(.SyncFragmentApplyError, serializedError)
Expand All @@ -42,7 +43,11 @@ class ScopeFetchReplyMessage: ReplyMessage {
if index == nil || replyTo == nil || (scopeIndex == nil && error == nil) {
return nil
} else {
return ScopeFetchReplyMessage(index: index!, replyTo: replyTo!, scopeIndex: scopeIndex, error: error)
return ScopeFetchReplyMessage(
index: index!,
replyTo: replyTo!,
scopeIndex: scopeIndex,
error: error)
}
}
}
4 changes: 2 additions & 2 deletions Jetstream/Session.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ public class Session {
switch message {
case let scopeStateMessage as ScopeStateMessage:
if let scope = scopes[scopeStateMessage.scopeIndex] {
if let rootModel = scope.rootModel {
if scope.root != nil {
scope.startApplyingRemote()
scope.applyRootFragment(scopeStateMessage.rootFragment, additionalFragments: scopeStateMessage.syncFragments)
scope.endApplyingRemote()
Expand All @@ -104,7 +104,7 @@ public class Session {
}
case let scopeSyncMessage as ScopeSyncMessage:
if let scope = scopes[scopeSyncMessage.scopeIndex] {
if let rootModel = scope.rootModel {
if scope.root != nil {
if scopeSyncMessage.syncFragments.count > 0 {
scope.startApplyingRemote()
scope.applySyncFragments(scopeSyncMessage.syncFragments)
Expand Down
24 changes: 12 additions & 12 deletions Jetstream/SessionCreateReplyMessage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,31 @@ class SessionCreateReplyMessage: NetworkMessage {
return SessionCreateReplyMessage.messageType
}

let success: Bool
let sessionToken: String
let response: AnyObject?
let sessionToken: String?
let error: NSError?

init(index: UInt, success: Bool, sessionToken: String, response: AnyObject?) {
self.success = success
init(index: UInt, sessionToken: String?, error: NSError?) {
self.sessionToken = sessionToken
self.response = response
super.init(index: index)
}

override class func unserialize(dictionary: [String: AnyObject]) -> NetworkMessage? {
var index = dictionary["index"] as? UInt
var success = dictionary["success"] as? Bool
var sessionToken = dictionary["sessionToken"] as? String
var response: AnyObject? = dictionary["response"]

if index == nil || success == nil || sessionToken == nil {

var error: NSError?
if let serializedError = dictionary["error"] as? [String: AnyObject] {
error = errorFromDictionary(.SyncFragmentApplyError, serializedError)
}

if index == nil || (sessionToken == nil && error == nil) {
return nil
} else {
return SessionCreateReplyMessage(
index: index!,
success: success!,
sessionToken: sessionToken!,
response: response)
sessionToken: sessionToken,
error: error)
}
}
}
8 changes: 4 additions & 4 deletions Jetstream/SyncFragment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,15 @@ public class SyncFragment: Equatable {
}

func applyChangesToScope(scope: Scope, applyDefaults: Bool = false) {
if (scope.rootModel == nil) {
if scope.root == nil {
return
}

switch type {
case .Root:
if let definiteRootModel = scope.rootModel {
applyPropertiesToModelObject(definiteRootModel, scope: scope, applyDefaults: applyDefaults)
scope.updateUUIDForModel(definiteRootModel, uuid: self.objectUUID)
if let rootModel = scope.root {
applyPropertiesToModelObject(rootModel, scope: scope, applyDefaults: applyDefaults)
scope.updateUUIDForModel(rootModel, uuid: self.objectUUID)
}
case .Change:
if let modelObject = scope.getObjectById(objectUUID) {
Expand Down
28 changes: 15 additions & 13 deletions JetstreamDemos/JetstreamDemos/ShapesDemoViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import UIKit
import Jetstream

class ShapesDemoViewController: UIViewController, NSURLConnectionDataDelegate {
var scope = Scope(name: "ShapesDemo")
var scope = Scope(name: "Canvas")
var canvas = Canvas()

var client: Client?
Expand All @@ -23,8 +23,8 @@ class ShapesDemoViewController: UIViewController, NSURLConnectionDataDelegate {

let tapRecognizer = UITapGestureRecognizer(target: self, action: Selector("handleTap:"))
self.view.addGestureRecognizer(tapRecognizer)
canvas.setScopeAndMakeRootModel(scope)

scope.root = canvas
canvas.observeCollectionAdd(self, key: "shapes") { (element: Shape) in
let shapeView = ShapeView(shape: element)
self.view.addSubview(shapeView)
Expand All @@ -44,18 +44,20 @@ class ShapesDemoViewController: UIViewController, NSURLConnectionDataDelegate {
super.viewWillAppear(animated)
showLoader()

let transportAdapter = WebsocketTransportAdapter(options: WebsocketConnectionOptions(url: NSURL(string: "ws://" + host + ":3000")!))
let options = WebsocketConnectionOptions(url: NSURL(string: "ws://" + host + ":3000")!)
let transportAdapter = WebsocketTransportAdapter(options: options)
client = Client(transportAdapter: transportAdapter)
client?.connect()
client?.onSession.listenOnce(self) { (session) in
self.session = session
let scope = self.scope
session.fetch(scope) { (error) in
if error != nil {
self.alertError("Error fetching scope", message: "\(error)")
} else {
self.hideLoader()
}
client?.onSession.listenOnce(self) { [unowned self] in self.sessionDidStart($0) }
}

func sessionDidStart(session: Session) {
self.session = session
session.fetch(scope) { error in
if error != nil {
self.alertError("Error fetching scope", message: "\(error)")
} else {
self.hideLoader()
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion JetstreamTests/StateMessageTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class StateMessageTests: XCTestCase {
XCTAssertEqual(scope.modelObjects.count, 1, "Correct number of objects in scope to start with")

client = Client(transportAdapter: WebSocketTransportAdapter(options: WebSocketConnectionOptions(url: NSURL(string: "localhost")!)))
var msg = SessionCreateReplyMessage(index: 1, success: true, sessionToken: "jeah", response: nil)
var msg = SessionCreateReplyMessage(index: 1, sessionToken: "jeah", error: nil)
client.receivedMessage(msg)
client.session!.scopeAttach(scope, scopeIndex: 1)

Expand Down
2 changes: 1 addition & 1 deletion JetstreamTests/TransactionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class TransactionTests: XCTestCase {
scope.getAndClearSyncFragments()

client = Client(transportAdapter: WebSocketTransportAdapter(options: WebSocketConnectionOptions(url: NSURL(string: "localhost")!)))
var msg = SessionCreateReplyMessage(index: 1, success: true, sessionToken: "jeah", response: nil)
var msg = SessionCreateReplyMessage(index: 1, sessionToken: "jeah", error: nil)
client.receivedMessage(msg)
client.session!.scopeAttach(scope, scopeIndex: 1)
}
Expand Down
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ Once you've defined your model classes, instante a canvas and mark it as a scope

```swift
var canvas = Canvas()
canvas.isScopeRoot = true

var scope = Scope(name: "Canvas")
scope.root = canvas
```
This will create a new scope and assign `canvas` as the root of the scope. The root object or any branches or leafs attached now belong to the scope. This lets you start observing changes happening to any models that have been attached to the tree:

Expand Down