I'm self-hosting Appwrite version 1.5 as a backend for an iOS app and trying to leverage the realtime module with the Apple SDK.
It's taken me a couple of days to start to get any response at all from it, but now that I am, I have a question.
Is it true that if I want to be alerted when a new document is created in a specific collection, I have to subscribe to the channel:
"databases.<mydb_id>.collections.<mycollection_id>.documents"
...and that I cannot subscribe to:
"databases.<mydb_id>.collections.<mycollection_id>.documents.*.create"
... and that that means I will receive an event with a payload comprised of the full document, for every document that is updated in this collection while my subscription is active - and not just the newly created documents that I am interested in? Even if I ignore events that are not .create events, there will be a LOT of extra data crossing the internet and significant unnecessary local processing.
Documents in this particular collection are expected to be updated frequently - every few seconds but I only need those updates from devices that have subscribed to a specific document. This process to listen for new documents is intended to present a list of documents the user can choose ONE of - after which I will start a new subscription to listen to just events pertaining to that one document. (But there could very well be thousands of documents that are being updated every 2-3 seconds.)
Am I misunderstanding how this works?
Is there any way to eliminate all that waste and to get only the events and payloads for newly created documents?
Yes, as far as I see thatβs true, so it is not possible
I also updated the code in both functions to call:
realtime.subscribe(channel: channel)
instead of
realtime.subscribe(channels: Set(channelArray))
but there is no difference in behavior.
I got an ugly workaround working - but only as a troubleshooting aid. If I instantiate a 2nd instance of Realtime() like so:
class Appwrite {
static let shared = Appwrite()
var client: Client
var account: Account
var databases: Databases
var functions: Functions
**var realtime: Realtime**
**var realtime2: Realtime**
var gameUpdateSubscription: RealtimeSubscription?
var gameInProgressCollectionSubscription: RealtimeSubscription?
var gameInProgressTestSub: RealtimeSubscription?
public init() {
self.client = Client()
.setEndpoint("https://appwrite.myserver.app/v1")
.setProject("6605dc1c00272e912cc8") // Your project ID
self.account = Account(client)
self.functions = Functions(client)
**self.realtime = Realtime(client)**
**self.realtime2 = Realtime(client)**
self.databases = Databases(client)
}
And I subscribe to the first listener with realtime.subscribe() and the second listener with realtime2.subscribe() - then both listeners work properly at the same time (but presumably with 2 websocket connections instead of just the one). It's not something I can use - but it does prove (again) that both subscribe() calls are valid.
Can you add print statements here to check if data is coming through from Appwrite?
Wait...the subscribed to channels is all the same π
Where do you want me to add the print statments?
What I linked in my message
Not sure where you mean...
This message βοΈ
Yeah - and that's where I've been adding a bunch of print statements - but I don't know what you mean by "to verify the data is coming through". In which function? We know "some" data is coming through because I get the events for the first subscription. Where do I need to add logging to log information about the event that is NOT coming through? To me, it sounds like you're saying "Raise your hand if you are not here!" π
Do you not see that link on the data
word?
Yes - but I thought it just linked to "Realtime.swift" so I didn't click it and just opened the file locally. I didn't realize that it pointed to a specific line within it! But instead of just repeating the same link over and over when I obviously didn't understand what you meant, perhaps you might have elaborated sooner - or simply said "in the onMessage() function"? lol I'll add a print statement now.
The output is too long to paste, but I started the app which initiates the first listener. OnMessage() didn't appear in the log. Then I created a new game from another device and the original device received the event and logged data from the onMessage() call. Then I paused the game on the 2nd device and tapped the new game on the test device to initiate the subscription.
2024-05-09 20:16:27 - tableView(_:didSelectRowAt:): Subscribing to game updates for docId: 663d66bfa93d0c5b5799
2024-05-09 20:16:27 - fetchGameInProgress(docId:): Received 663d66bfa93d0c5b5799 lastUpdated: 2024-05-10T00:13:53.551+00:00
2024-05-09 20:16:27 - fetchGameInProgress(docId:): Received Document with ID: 663d66bfa93d0c5b5799
2024-05-09 20:16:27 - fetchGameInProgress(docId:): -- game-in-progress Game ID: 2VL6
2024-05-09 20:16:27 - subscribeToGameUpdates(docId:callbackVC:): Subscribing to channels: databases.6605e1b40033ee096f28.collections.games-in-progress.documents.663d66bfa93d0c5b5799
Subscribed (A) to channel: databases.6605e1b40033ee096f28.collections.games-in-progress.documents.663d66bfa93d0c5b5799
Subscribed (B) to 1 channels:
subscribe:channels:payloadType:callback:()-- Channel: databases.6605e1b40033ee096f28.collections.games-in-progress.documents.663d66bfa93d0c5b5799
subscribe:channels:payloadType:callback:() Active Subscriptions: 2
-- Active Subscription Key:2 CB: ["databases.6605e1b40033ee096f28.collections.games-in-progress.documents.663d66bfa93d0c5b5799"]
-- Active Subscription Key:1 CB: ["databases.6605e1b40033ee096f28.collections.gameinprogress-docids.documents"]
2024-05-09 20:16:27 - subscribeToGameUpdates(docId:callbackVC:): gameUpdateSubscription established: Optional(Appwrite.RealtimeSubscription)
Then I resumed the game on the 2nd device - but no events or onMessage() data was received by the test device.
My logging shows that there are 2 active subscriptions (like it should). But no events are received for the second one.
An event only comes through when there's some operation. Nothing comes through when you first subscribe
Understood. But events should have come through after I resumed the game on the 2nd device - but they didn't.
If I restart the test device with the first subscription commented out - those game events DO come through properly.
So it seems like when there is more than one subscription, the 2nd one doesn't get properly registered on the server?
@Jake, it looks like we only pass the url (and channels) in once, so a second subscribe call won't get the new channels, right?
We only maintain one connection but a second call to subscribe will add the new channels, close the current connection, then open a new one with all channels included. The events that are received are then sent to the right callback depending on the channels they subscribed with
How do the new channels get added because it seems like the url is only passed in when the socket is initialized and not on close and connect? See https://github.com/appwrite/sdk-for-apple/blob/c39030db9af1e2dd7b36f8df45f838c5f7dfb0da/Sources/Appwrite/Services/Realtime.swift#L41
Ya but how does the url get passed into the socket?
Recommended threads
- Error: User (role: guests) missing scope...
I want to send a verification code to the user and the given phone number and check it and create a session right after the user entered the secret. For me that...
- Sign In With Apple OAuth Help
Hi All! I've got a flutter & appwrite app which Im trying to use sign in with apple for. I already have sign in with google working and the function is the sam...
- Type Mismatch in AppwriteException
There is a discrepancy in the TypeScript type definitions for AppwriteException. The response property is defined as a string in the type definitions, but in pr...