-
Notifications
You must be signed in to change notification settings - Fork 36
chore: offload conversation calculation - WPB-17293 #2921
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
Changes from 18 commits
6408b22
4ff23a1
20c3ddb
de354be
ac31a04
a16f7ad
bc2d602
2c10e5f
9e27b8f
2b91715
7c2e089
b9b9e6d
2e9544e
9b12b59
b4d5260
5e26e30
92e8676
cfee156
a17543a
da42bdb
665835f
4393a72
6564e7f
914a6d1
2d78a75
1e52fe6
2ba7896
d628c27
953e908
1534aeb
0bca79e
563c055
3d089bc
4844918
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| // | ||
| // Wire | ||
| // Copyright (C) 2025 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/. | ||
| // | ||
|
|
||
| public import Foundation | ||
|
|
||
| public final class LeadingTrailingDebouncer<ID: Hashable> { | ||
|
johnxnguyen marked this conversation as resolved.
|
||
|
|
||
| private struct DebounceState { | ||
| var isCooldown = false | ||
| var pendingCall: (() -> Void)? | ||
| } | ||
|
|
||
| private let cooldownTime: TimeInterval | ||
| private let queue: DispatchQueue | ||
| private var states: [AnyHashable: DebounceState] = [:] | ||
|
|
||
| // Unique key for `nil` ID | ||
| private let nilKey = UUID() | ||
|
|
||
| public init(cooldownTime: TimeInterval, queue: DispatchQueue = .main) { | ||
| self.cooldownTime = cooldownTime | ||
| self.queue = queue | ||
| } | ||
|
|
||
| public func call(id: ID?, block: @escaping () -> Void) { | ||
|
|
||
| let key: AnyHashable = id.map { AnyHashable($0) } ?? AnyHashable(nilKey) | ||
|
|
||
| if states[key] == nil { | ||
| states[key] = DebounceState() | ||
| } | ||
|
|
||
| var state = states[key]! | ||
|
|
||
| if !state.isCooldown { | ||
| // LEADING: run immediately | ||
| block() | ||
| state.isCooldown = true | ||
|
|
||
| queue.asyncAfter(deadline: .now() + cooldownTime) { [weak self] in | ||
|
Check warning on line 55 in WireFoundation/Sources/WireFoundation/LeadingTrailingDebouncer.swift
|
||
| guard let self else { return } | ||
|
|
||
|
Check warning on line 57 in WireFoundation/Sources/WireFoundation/LeadingTrailingDebouncer.swift
|
||
| var updatedState = states[key] ?? DebounceState() | ||
| updatedState.isCooldown = false | ||
|
|
||
| if let trailing = updatedState.pendingCall { | ||
| trailing() | ||
| updatedState.pendingCall = nil | ||
| updatedState.isCooldown = true | ||
|
|
||
| queue.asyncAfter(deadline: .now() + cooldownTime) { | ||
|
Check warning on line 66 in WireFoundation/Sources/WireFoundation/LeadingTrailingDebouncer.swift
|
||
| self.states[key]?.isCooldown = false | ||
| self.states[key]?.pendingCall = nil | ||
| } | ||
| } | ||
|
|
||
| states[key] = updatedState | ||
| } | ||
| } else { | ||
| // Store for TRAILING | ||
| state.pendingCall = block | ||
| } | ||
|
|
||
| states[key] = state | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| // | ||
| // Wire | ||
| // Copyright (C) 2025 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 Foundation | ||
|
|
||
| public class ThreadSafeDictionary<Key: Hashable, Value> { | ||
|
|
||
| public init() {} | ||
|
|
||
| private var dictionary = [Key: Value]() | ||
| private let queue = DispatchQueue(label: "com.example.dictionaryQueue") | ||
|
|
||
| public func set(value: Value?, for key: Key) { | ||
| queue.async { | ||
|
Check warning on line 29 in WireFoundation/Sources/WireFoundation/ThreadSafeDictionary.swift
|
||
| self.dictionary[key] = value | ||
| } | ||
| } | ||
|
|
||
| public func get(for key: Key) -> Value? { | ||
| queue.sync { | ||
| self.dictionary[key] | ||
| } | ||
| } | ||
|
|
||
| public func remove(for key: Key) { | ||
| queue.async { | ||
|
Check warning on line 41 in WireFoundation/Sources/WireFoundation/ThreadSafeDictionary.swift
|
||
| self.dictionary.removeValue(forKey: key) | ||
| } | ||
| } | ||
|
|
||
| public func allItems() -> [Key: Value] { | ||
| queue.sync { | ||
| self.dictionary | ||
| } | ||
| } | ||
|
|
||
| public func reset() { | ||
| queue.async { | ||
|
Check warning on line 53 in WireFoundation/Sources/WireFoundation/ThreadSafeDictionary.swift
|
||
| self.dictionary.removeAll() | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,7 +121,7 @@ | |
| public let accountContainer: URL | ||
| public let applicationContainer: URL | ||
|
|
||
| let messagesContainer: PersistentContainer | ||
| public let messagesContainer: PersistentContainer | ||
| let eventsContainer: PersistentContainer | ||
| let dispatchGroup: ZMSDispatchGroup? | ||
|
|
||
|
|
@@ -562,14 +562,14 @@ | |
|
|
||
| // MARK: - | ||
|
|
||
| class PersistentContainer: NSPersistentContainer { | ||
| public class PersistentContainer: NSPersistentContainer { | ||
|
|
||
| var storeURL: URL? { | ||
| persistentStoreDescriptions.first?.url | ||
| } | ||
|
|
||
| var storeExists: Bool { | ||
| guard let storeURL else { | ||
|
Check warning on line 572 in wire-ios-data-model/Source/ManagedObjectContext/CoreDataStack.swift
|
||
| return false | ||
| } | ||
|
|
||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.