Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: implement new NSE mechanism and pull pending events - WPB-10219 #2287

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Foundation

/// An event concerning feature configs.

public enum FeatureConfigEvent: Equatable, Codable {
public enum FeatureConfigEvent: Equatable, Codable, Sendable {

/// A feature config was updated.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Foundation

/// An event concerning federation between domains.

public enum FederationEvent: Equatable, Codable {
public enum FederationEvent: Equatable, Codable, Sendable {

/// Two or more other domains have stopped federating
/// with each other.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import Foundation

/// An event concerning teams.

public enum TeamEvent: Equatable, Codable {
public enum TeamEvent: Equatable, Codable, Sendable {

/// The self team was deleted.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

/// An event concerning users.

public enum UserEvent: Equatable, Codable {
public enum UserEvent: Equatable, Codable, Sendable {

/// The self user has added a new client.

Expand All @@ -35,7 +35,7 @@
case connection(UserConnectionEvent)

/// A contact has joined Wire.

Check warning on line 38 in WireAPI/Sources/WireAPI/Models/UpdateEvent/UserEvent/UserEvent.swift

View workflow job for this annotation

GitHub Actions / Test Results

Associated value 'contactJoin' of 'Sendable'-conforming enum 'UserEvent' has non-sendable type 'UserContactJoinEvent'; this is an error in the Swift 6 language mode

Associated value 'contactJoin' of 'Sendable'-conforming enum 'UserEvent' has non-sendable type 'UserContactJoinEvent'; this is an error in the Swift 6 language mode
case contactJoin(UserContactJoinEvent)

/// A user was deleted.
Expand All @@ -55,7 +55,7 @@
case legalholdRequest(UserLegalholdRequestEvent)

/// One of the self user's persisted properties was set.

Check warning on line 58 in WireAPI/Sources/WireAPI/Models/UpdateEvent/UserEvent/UserEvent.swift

View workflow job for this annotation

GitHub Actions / Test Results

Associated value 'propertiesSet' of 'Sendable'-conforming enum 'UserEvent' has non-sendable type 'UserPropertiesSetEvent'; this is an error in the Swift 6 language mode

Associated value 'propertiesSet' of 'Sendable'-conforming enum 'UserEvent' has non-sendable type 'UserPropertiesSetEvent'; this is an error in the Swift 6 language mode
case propertiesSet(UserPropertiesSetEvent)

/// One of the self user's persisted properties was deleted.
Expand Down
52 changes: 0 additions & 52 deletions WireDomain/Project/WireDomain Project.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -365,58 +365,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
C9D57B232CF75B3700012A0E /* FeatureConfigRepositoryTests.swift in Sources */,
C9F691292C9B164A008CC41F /* UserPushRemoveEventProcessorTests.swift in Sources */,
C96B757B2CDDEDC4003A85EB /* ConversationLabelsLocalStoreTests.swift in Sources */,
C9D5804A2CFF637600012A0E /* MessageLocalStoreTests.swift in Sources */,
C96B75292CDB7688003A85EB /* ConversationMemberUpdateEventProcessorTests.swift in Sources */,
C96B752A2CDB7688003A85EB /* ConversationMemberJoinEventTests.swift in Sources */,
C96B752B2CDB7688003A85EB /* ConversationProtocolUpdateEventProcessorTests.swift in Sources */,
C96B752C2CDB7688003A85EB /* ConversationAccessUpdateEventProcessorTests.swift in Sources */,
C96B755F2CDBCD24003A85EB /* UserLocalStoreTests.swift in Sources */,
C96B752D2CDB7688003A85EB /* ConversationCreateEventProcessorTests.swift in Sources */,
C96B752E2CDB7688003A85EB /* ConversationReceiptModeUpdateEventProcessorTests.swift in Sources */,
C96B752F2CDB7688003A85EB /* ConversationMemberLeaveEventTests.swift in Sources */,
C93961922C91B12800EA971A /* TestError.swift in Sources */,
EEC410262C60D48900E89394 /* SyncManagerTests.swift in Sources */,
C9C8FDD32C9DBE0E00702B91 /* UserLegalHoldDisableEventProcessorTests.swift in Sources */,
EE57A7032C2994420096F242 /* UpdateEventsRepositoryTests.swift in Sources */,
C98433F12CCBC251009723D4 /* MessageRepositoryTests.swift in Sources */,
C9C8FDD02C9DBE0E00702B91 /* TeamMemberLeaveEventProcessorTests.swift in Sources */,
C97C01A82CB813C9000683C5 /* UserClientsRepositoryTests.swift in Sources */,
C9841A1F2CA309310062A834 /* MockFeatureConfigRepositoryProtocol.swift in Sources */,
C97C015C2CB40038000683C5 /* UserPropertiesSetEventProcessorTests.swift in Sources */,
CB7979162C738547006FBA58 /* TestSetup.swift in Sources */,
162356502C2B223100C6666C /* UserRepositoryTests.swift in Sources */,
C96B75452CDBA0A9003A85EB /* ConversationDeleteEventProcessorTests.swift in Sources */,
EE3F97542C2ADC4C00668DF1 /* ProteusMessageDecryptorTests.swift in Sources */,
C9D57A932CF7556800012A0E /* ConversationRepositoryTests.swift in Sources */,
EE57A70B2C2A8BAA0096F242 /* UpdateEventDecryptorTests.swift in Sources */,
C9E8A3AE2C73878B0093DD5C /* ConnectionsRepositoryTests.swift in Sources */,
C97C01BB2CBE5E65000683C5 /* UserUpdateEventProcessorTests.swift in Sources */,
C9C1024E2CE7984300EA273F /* OneOnOneResolverTests.swift in Sources */,
C97C013D2CAD7D69000683C5 /* UserPropertiesDeleteEventProcessorTests.swift in Sources */,
C9D574582CEB9FB400012A0E /* ConversationRenameEventProcessorTests.swift in Sources */,
C96B75612CDCAFC6003A85EB /* ConnectionsLocalStoreTests.swift in Sources */,
C9C8FDD22C9DBE0E00702B91 /* UserClientAddEventProcessorTests.swift in Sources */,
C96B756D2CDCFA36003A85EB /* FeatureConfigLocalStoreTests.swift in Sources */,
C9C8FDD12C9DBE0E00702B91 /* TeamMemberUpdateEventProcessorTests.swift in Sources */,
C9C1024C2CE7935600EA273F /* UserConnectionEventProcessorTests.swift in Sources */,
C97C01542CB04626000683C5 /* UserDeleteEventProcessorTests.swift in Sources */,
C96B75672CDCD3BC003A85EB /* UserClientsLocalStoreTests.swift in Sources */,
C9C8FDCE2C9DBE0E00702B91 /* FeatureConfigUpdateEventProcessorTests.swift in Sources */,
C9C8FDCF2C9DBE0E00702B91 /* TeamDeleteEventProcessorTests.swift in Sources */,
C97C01592CB40010000683C5 /* FederationConnectionRemovedEventProcessorTests.swift in Sources */,
C9D580482CFF57D500012A0E /* ConversationMLSWelcomeEventProcessorTests.swift in Sources */,
C97C01AC2CB92D47000683C5 /* UserLegalholdEnableEventProcessorTests.swift in Sources */,
C96B75652CDCC85B003A85EB /* TeamLocalStoreTests.swift in Sources */,
C96B75702CDD0000003A85EB /* MockFeatureConfigLocalStoreProtocol.swift in Sources */,
C97C015A2CB40010000683C5 /* FederationDeleteEventProcessorTests.swift in Sources */,
C9C8FDD42C9DBE0E00702B91 /* UserLegalholdRequestEventProcessorTests.swift in Sources */,
C96B755D2CDBB176003A85EB /* ConversationLocalStoreTests.swift in Sources */,
C96B75772CDD154C003A85EB /* UpdateEventsLocalStoreTests.swift in Sources */,
017F679C2C20801800B6E02D /* TeamRepositoryTests.swift in Sources */,
C9E8A3B72C749F2A0093DD5C /* ConversationLabelsRepositoryTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
113 changes: 113 additions & 0 deletions WireDomain/Sources/WireDomain/Assembly.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//
// Wire
// Copyright (C) 2024 Wire Swiss GmbH
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//

import WireAPI
import WireDataModel
import WireFoundation

public final class Assembly {

private let userID: UUID
private let clientID: String
private let context: NSManagedObjectContext
private let sharedUserDefaults: UserDefaults
private let proteusService: any ProteusServiceInterface
private let apiService: any APIServiceProtocol
private let apiVersion: WireAPI.APIVersion
private let pushChannel: any PushChannelProtocol
private let cookieStorage: ZMPersistentCookieStorage

init(
userID: UUID,
clientID: String,
context: NSManagedObjectContext,
sharedUserDefaults: UserDefaults,
proteusService: any ProteusServiceInterface,
apiService: any APIServiceProtocol,
apiVersion: WireAPI.APIVersion,
pushChannel: any PushChannelProtocol,
cookieStorage: ZMPersistentCookieStorage
) {
self.userID = userID
self.clientID = clientID
self.context = context
self.sharedUserDefaults = sharedUserDefaults
self.proteusService = proteusService
self.apiService = apiService
self.apiVersion = apiVersion
self.pushChannel = pushChannel
self.cookieStorage = cookieStorage

registerNotificationServiceDependencies()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So just for my understanding, when and where would we initialize the Assembly.

One thing to have in mind there can be multiple process of NSE or iOS can reuse the same process to process different notifications payload

Copy link
Contributor Author

@jullianm jullianm Jan 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what I had in mind is that the assembly is the entry point of WireDomain so when the app starts, we use that entry point to setup all of our dependencies, we also take that occasion to register (using the lightweight DI mechanism Injector) some of the dependencies the notification service needs so we don't have to initialize them again every time we receive a new notification.

For instance, the NotificationSession is initialized everytime we receive a new notification, given some of these dependencies were already registered before, we can just resolve them and only pass variable userID which comes from the current notification payload :

let updateEventsRepository = UpdateEventsRepository(
            userID: userID,
            selfClientID: selfClientID,
            // these were already initialized, resolving them
            updateEventsAPI: Injector.resolve(),
            pushChannel: Injector.resolve(),
            updateEventDecryptor: Injector.resolve(),
            updateEventsLocalStore: Injector.resolve()
        )

also mentioning @johnxnguyen because it is related

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sounds good

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@netbe, you, and I are all facing the question of how to set up the dependency graph, and we all have various solutions. I propose we meet to find a common solution.

}

// MARK: - API Init

private lazy var updateEventsAPI = UpdateEventsAPIBuilder(
apiService: apiService
).makeAPI(for: apiVersion)

private lazy var updateEventDecryptor = UpdateEventDecryptor(
proteusService: proteusService,
context: context
)

// MARK: - Repositories and local stores Init

private lazy var userLocalStore = UserLocalStore(context: context)

private lazy var updateEventsLocalStore = UpdateEventsLocalStore(
context: context,
userID: userID,
sharedUserDefaults: sharedUserDefaults
)

}

extension Assembly {

/// Register some domain dependencies to be resolved by the `NotificationService`.
/// Since `NotificationService` is not initializable, the injector provides a lightweight dependency injection
/// mechanism to retrieve some already initialized dependencies that the notification service requires.

private func registerNotificationServiceDependencies() {
Injector.register(UserLocalStoreProtocol.self) {
self.userLocalStore
}

Injector.register(UpdateEventsAPI.self) {
self.updateEventsAPI
}

Injector.register(PushChannelProtocol.self) {
self.pushChannel
}

Injector.register(UpdateEventDecryptorProtocol.self) {
self.updateEventDecryptor
}

Injector.register(UpdateEventsLocalStoreProtocol.self) {
self.updateEventsLocalStore
}

Injector.register(ZMPersistentCookieStorage.self) {
self.cookieStorage
}
}
}
Loading
Loading