Skip to content
This repository has been archived by the owner on Jun 13, 2023. It is now read-only.

Emitted Events from WebSocket pings not forwarded to Subscription Handler #264

Open
4 tasks done
HackShitUp opened this issue Feb 3, 2023 · 4 comments
Open
4 tasks done
Labels

Comments

@HackShitUp
Copy link

HackShitUp commented Feb 3, 2023

New Issue Checklist

Issue Description

subscription?.handleEvent({ (query: PFQuery<PFObject>, event: Event<PFObject>) in
    print("Fired: \(#line)")
})

The Subscription.handleEvent protocol never gets called but WebSocket pings are received (logged in Client.shouldPrintWebSocketTrace)

Steps to reproduce

Define the client, and subscribe to a query the standard way:

let query = PFQuery(className: "Test")
query.whereKey("objectId", equalTo: "objectId")

client = ParseLiveQuery.Client(server: serverURL)
client?.shouldPrintWebSocketLog = true
client?.shouldPrintWebSocketTrace = true

subscription = client?.subscribe(query)
subscription?.handleEvent({ (query: PFQuery<PFObject>, event: Event<PFObject>) in
    print("Fired: \(#line)")
})

WebSocket trace logs received ping but does not forward to the protocol.

Actual Outcome

Event not forwarded at the ParseLiveQuery layer

Expected Outcome

All emitted events should be accessible by the Subscription's handler

Environment

Parse LiveQuery ObjC SDK

  • SDK version: 2.8.1
    • Bolts-Swift: 1.5.0
    • Parse: 1.19.0
  • Operating system version: iOS 16.0

Server

  • Parse Server version: 5.4.1
  • Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc): Remote/Local
@parse-github-assistant
Copy link

parse-github-assistant bot commented Feb 3, 2023

Thanks for opening this issue!

  • 🚀 You can help us to fix this issue faster by opening a pull request with a failing test. See our Contribution Guide for how to make a pull request, or read our New Contributor's Guide if this is your first time contributing.

@HackShitUp HackShitUp changed the title Subscription Not Forwarding WebSocket Pings from emitted Event Emitted Events from WebSocket pings not forwarded to Subscription Handler Feb 3, 2023
@432player
Copy link

I had the same issue.
Server Side:
"parse": "4.0.1",
"parse-server": "^6.0.0"

IOS Client Side:

  • Parse (1.19.4):
  • Parse/Core (= 1.19.4)
  • Parse/Core (1.19.4):
  • Bolts/Tasks (= 1.9.1)
  • ParseLiveQuery (2.8.1):
  • Bolts-Swift (~> 1.5.0)
  • Starscream (~> 4.0.4)

Apparently from some version of parse-server the received message from the ParseLiveQuery didn't return with the type on the main object in the string received. for example:
{
"op": "update",
"clientId": "559ca4bd-7425-4ea8-b7ed-8ac73e6c6d15",
"requestId": 2,
"object": {
"user1": {
"__type": "Pointer",
"className": "_User",
"objectId": "8YoD1R8RTJ"
},
"user2": {
"__type": "Pointer",
"className": "_User",
"objectId": "DrvZzHZASt"
},
"createdAt": "2023-05-16T09:57:29.412Z",
"updatedAt": "2023-05-20T20:13:46.736Z",
"messages": {
"__type": "Relation",
"className": "Message"
},
"className": "PrivateChat",
"objectId": "lsxP3br9EG"
},
"original": {
"user1": {
"__type": "Pointer",
"className": "_User",
"objectId": "8YoD1R8RTJ"
},
"user2": {
"__type": "Pointer",
"className": "_User",
"objectId": "DrvZzHZASt"
},
"createdAt": "2023-05-16T09:57:29.412Z",
"updatedAt": "2023-05-20T20:12:07.365Z",
"messages": {
"__type": "Relation",
"className": "Message"
},
"className": "PrivateChat",
"objectId": "lsxP3br9EG"
}
}
As you can see "object" has no type so parse doesn't know how to parse it into a PFObject.
that's why it says something like "bad json" when serializing it into PFObject.

So I've added a short code to always add a __type = "Object" into the Json for the first main "object" and I removed the original object, I don't see how original object is supported in the ParseLiveQuery-iOS-OSX library.

So the received json would now look like this:
{
"op": "update",
"clientId": "559ca4bd-7425-4ea8-b7ed-8ac73e6c6d15",
"requestId": 2,
"object": {
"user1": {
"__type": "Pointer",
"className": "_User",
"objectId": "8YoD1R8RTJ"
},
"user2": {
"__type": "Pointer",
"className": "_User",
"objectId": "DrvZzHZASt"
},
"createdAt": "2023-05-16T09:57:29.412Z",
"updatedAt": "2023-05-20T20:13:46.736Z",
"messages": {
"__type": "Relation",
"className": "Message"
},
"__type": "Object", //This is what I've added, and removed "original" key from the json.
"className": "PrivateChat",
"objectId": "lsxP3br9EG"
}
}

So in the function func handleOperationAsync(_ string: String) -> Task in ClientPrivate.swift I've changed the code to look like this:
func handleOperationAsync(_ string: String) -> Task {
return Task(.queue(queue)) {
if self.shouldPrintWebSocketTrace { NSLog("ParseLiveQuery: Received message: (string)") }
guard
let jsonData = string.data(using: .utf8),
let jsonDecoded = try JSONSerialization.jsonObject(with: jsonData, options: []) as? [String: AnyObject]
else {
throw LiveQueryErrors.InvalidResponseError(response: string)
}

//--------START CHANGED CODE HERE------//
var modifiedJson = jsonDecoded
// Remove the "original" key if present
modifiedJson.removeValue(forKey: "original")

        if let object = modifiedJson["object"] as? [String: AnyObject] {
            modifiedJson["object"] = addTypeToObject(object) as AnyObject
        }
 

        guard let response: ServerResponse = try? ServerResponse(json: modifiedJson) else {
            throw LiveQueryErrors.InvalidResponseError(response: string)
        }

        func addTypeToObject(_ object: [String: AnyObject]) -> [String: AnyObject] {
            var modifiedObject = object
            for (key, value) in modifiedObject {
                if key == "className" && !(value is [String: AnyObject]) {
                    modifiedObject["__type"] = "Object" as AnyObject
                    break
                }
            }
            return modifiedObject
        }

//--------END CHANGED CODE HERE------//
switch response {
case .connected:
let sessionToken = PFUser.current()?.sessionToken
self.subscriptions.forEach {
_ = self.sendOperationAsync(.subscribe(requestId: $0.requestId, query: $0.query, sessionToken: sessionToken))
}

        case .redirect:
            // TODO: Handle redirect.
            break

        case .subscribed(let requestId):
            self.subscriptionRecord(requestId)?.subscribeHandlerClosure(self)

        case .unsubscribed(let requestId):
            guard
                let recordIndex = self.subscriptions.firstIndex(where: { $0.requestId == requestId })
                 else {
                    break
            }
            let record: SubscriptionRecord = self.subscriptions[recordIndex]
            record.unsubscribeHandlerClosure(self)
            self.subscriptions.remove(at: recordIndex)

        case .create, .delete, .enter, .leave, .update:
            var requestId: RequestId = RequestId(value: 0)
            guard
                let event: Event<PFObject> = try? Event(serverResponse: response, requestId: &requestId),
                let record = self.subscriptionRecord(requestId)
            else {
                break
            }
           
            record.eventHandlerClosure(event, self)
        case .error(let requestId, let code, let error, let reconnect):
            let error = LiveQueryErrors.ServerReportedError(code: code, error: error, reconnect: reconnect)
            if let requestId = requestId {
                self.subscriptionRecord(requestId)?.errorHandlerClosure(error, self)
            } else {
                throw error
            }
        }
    }
}

I hope that this will be taken care of by the library itself cause if I update the library I will always have to remember to add this code.
Perhaps if there's is no type assume that it is "__type" = "Object" or something if it's missing, not really sure what the best way would be. but I would appreciate it if this can be fixed internally.

Much blessings

@mtrezza
Copy link
Member

mtrezza commented May 22, 2023

Does anyone want to open a PR and propose a solution?

@mtrezza
Copy link
Member

mtrezza commented Jun 13, 2023

@432player, @HackShitUp The LiveQuery feature has been added as a module to the Parse Apple SDK; could you please verify that this issue is fixed there, and if not open a new issue there?

@mtrezza mtrezza closed this as completed Jun 13, 2023
@mtrezza mtrezza reopened this Jun 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

3 participants