Realm Swift Subscriptions - BEST PRACTICES

In realm swift what is the best practice for subscription management?

Say we have 3 classes:

class User: Object, ObjectKeyIdentifiable {
	@Persisted(primaryKey: true) var _id: ObjectId
	@Peristed(originProperty: "creator") var myEvents: LinkingObject<Event>
	@Peristed(originProperty: "user") var myInvitations: LinkingObject<Invitation>
}

class Event: Object, ObjectKeyIdentifiable {
	@Persisted(primaryKey: true) var _id: ObjectId
	@Persisted var mainHost: User?
	@Persisted var coHosts: List<User>
	@Peristed(originProperty: "event") var guestlist: LinkingObject<Invitation>

	@Persisted var listener_ids: MutableSet<ObjectId> /// IDs of the hosts
}

class Invitation: Object, ObjectKeyIdentifiable {
	@Persisted(primaryKey: true) var _id: ObjectId
	@Persisted var user: User?
	@Persited var comingWith: List<User>
	@Peristed var event: Event?
	
	@Persisted var listener_ids: MutableSet<ObjectId> /// IDs of users and event
}

To sync “expand” the Event I have to do the following


	@MainActor
	func syncHosts(event: Event) async throws {
		guard let subs = realm?.subscriptions else {
			throw RealmError.missingSubscriptions
		}
		
		try await subs.update {
			for userID in event.listener_ids {
				if subs.first(name: "user:\(userID.stringValue)") == nil {
					subs.append(QuerySubscription<User>(name: "user:\(user._id.stringValue)", query: {
						$0._id = userID
					}))
				} 
			}
		}
	}

OR


	@MainActor
	func syncHosts(event: Event) async throws {
		guard let subs = realm?.subscriptions else {
			throw RealmError.missingSubscriptions
		}
		
		try await subs.update {
		
			for userID in event.listener_ids {
				let user = realm.object(ofType: User, forPrimaryKey: userID)
				if (user == nil) || (user.isInvalidated == true) {
					subs.append(QuerySubscription<User>({
						$0._id == userID
					}))
				}
			}
		}
	}

This already feels dirty and gets worse when we want to expand Invitations.


	@Mainactor 
	func STEP1InvitationsForEvent(event: Event) async throws {
		guard let subs = realm?.subscriptions else {
			throw RealmError.missingSubscriptions
		}
		
		try await subs.update {
			// first
			if subs.first(name: "event:invitaitons\(event._id.stringValue)") == nil {
				subs.append(QuerySubscription<Invitation>(name: "event:invitaitons\(event._id.stringValue)", query: {
					$0.listener_ids.contains(event._id)
				}))
			}
		}
	}

@MainActor 
func STEP2SyncGuests(invitation: Invitation, eventID: ObjectID) async throws {
		guard let subs = realm?.subscriptions else {
			throw RealmError.missingSubscriptions
		}
		
		try await subs.update {
			for id in invitation.listener_ids {
				if (id != eventID) {
					if subs.first(name: "user:\(id.stringValue)") == nil {
						subs.append(QuerySubscription<User>(name: "user:\(id.stringValue)", query: {
						$0._id == id
						}))
					}
				}
			}
		}
	}

Is it enough to check QuerySubscription names? Or should we check of the realm object is invalidated? Or both?

Furthermore, say we have a list of rows for invitations. Should STEP2SyncGuests be ran as a task on the views? It seems like a lot of work on the main thread. What is the best practice here? Perhaps run the subscriptions in the background? Or a completely different approach?

Please not i’m not sure the code above compiles it’s only for getting the question out there.