Skip to content

Commit 362b72b

Browse files
authored
Merge pull request #984 from oxen-io/dev
Release 2.6.2
2 parents de41f5a + ec72a53 commit 362b72b

File tree

21 files changed

+444
-192
lines changed

21 files changed

+444
-192
lines changed

.drone.jsonnet

+1-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ local sim_delete_cmd = 'if [ -f build/artifacts/sim_uuid ]; then rm -f /Users/$U
227227
name: 'Build',
228228
commands: [
229229
'mkdir build',
230-
'NSUnbufferedIO=YES set -o pipefail && xcodebuild archive -workspace Session.xcworkspace -scheme Session -derivedDataPath ./build/derivedData -parallelizeTargets -configuration "App Store Release" -sdk iphonesimulator -archivePath ./build/Session_sim.xcarchive -destination "generic/platform=iOS Simulator" | xcbeautify --is-ci',
230+
'NSUnbufferedIO=YES set -o pipefail && xcodebuild archive -workspace Session.xcworkspace -scheme Session -derivedDataPath ./build/derivedData -parallelizeTargets -configuration "App_Store_Release" -sdk iphonesimulator -archivePath ./build/Session_sim.xcarchive -destination "generic/platform=iOS Simulator" | xcbeautify --is-ci',
231231
],
232232
depends_on: [
233233
'Install CocoaPods',

Session.xcodeproj/project.pbxproj

+12-4
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,8 @@
870870
FDD250722837234B00198BDA /* MediaGalleryNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */; };
871871
FDD82C3F2A205D0A00425F05 /* ProcessResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDD82C3E2A205D0A00425F05 /* ProcessResult.swift */; };
872872
FDDC08F229A300E800BF9681 /* LibSessionTypeConversionUtilitiesSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDDC08F129A300E800BF9681 /* LibSessionTypeConversionUtilitiesSpec.swift */; };
873+
FDDD554C2C1FC812006CBF03 /* CheckForAppUpdatesJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDDD554B2C1FC812006CBF03 /* CheckForAppUpdatesJob.swift */; };
874+
FDDD554E2C1FCB77006CBF03 /* _019_ScheduleAppUpdateCheckJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDDD554D2C1FCB77006CBF03 /* _019_ScheduleAppUpdateCheckJob.swift */; };
873875
FDDF074429C3E3D000E5E8B5 /* FetchRequest+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDDF074329C3E3D000E5E8B5 /* FetchRequest+Utilities.swift */; };
874876
FDDF074A29DAB36900E5E8B5 /* JobRunnerSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDDF074929DAB36900E5E8B5 /* JobRunnerSpec.swift */; };
875877
FDE125232A837E4E002DA685 /* MainAppContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE125222A837E4E002DA685 /* MainAppContext.swift */; };
@@ -2065,6 +2067,8 @@
20652067
FDD250712837234B00198BDA /* MediaGalleryNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MediaGalleryNavigationController.swift; sourceTree = "<group>"; };
20662068
FDD82C3E2A205D0A00425F05 /* ProcessResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessResult.swift; sourceTree = "<group>"; };
20672069
FDDC08F129A300E800BF9681 /* LibSessionTypeConversionUtilitiesSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LibSessionTypeConversionUtilitiesSpec.swift; sourceTree = "<group>"; };
2070+
FDDD554B2C1FC812006CBF03 /* CheckForAppUpdatesJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckForAppUpdatesJob.swift; sourceTree = "<group>"; };
2071+
FDDD554D2C1FCB77006CBF03 /* _019_ScheduleAppUpdateCheckJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _019_ScheduleAppUpdateCheckJob.swift; sourceTree = "<group>"; };
20682072
FDDF074329C3E3D000E5E8B5 /* FetchRequest+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FetchRequest+Utilities.swift"; sourceTree = "<group>"; };
20692073
FDDF074929DAB36900E5E8B5 /* JobRunnerSpec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobRunnerSpec.swift; sourceTree = "<group>"; };
20702074
FDE125222A837E4E002DA685 /* MainAppContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainAppContext.swift; sourceTree = "<group>"; };
@@ -3755,6 +3759,7 @@
37553759
FDFE75B02ABD2D2400655640 /* _016_MakeBrokenProfileTimestampsNullable.swift */,
37563760
FD428B222B4B9969006D0888 /* _017_RebuildFTSIfNeeded_2_4_5.swift */,
37573761
7B5233C5290636D700F8F375 /* _018_DisappearingMessagesConfiguration.swift */,
3762+
FDDD554D2C1FCB77006CBF03 /* _019_ScheduleAppUpdateCheckJob.swift */,
37583763
);
37593764
path = Migrations;
37603765
sourceTree = "<group>";
@@ -4454,6 +4459,7 @@
44544459
FD2B4AFE2946C93200AB4848 /* ConfigurationSyncJob.swift */,
44554460
7B7E5B512A4D024C00A8208E /* ExpirationUpdateJob.swift */,
44564461
7B7AD41E2A5512CA00469FB1 /* GetExpirationJob.swift */,
4462+
FDDD554B2C1FC812006CBF03 /* CheckForAppUpdatesJob.swift */,
44574463
);
44584464
path = Types;
44594465
sourceTree = "<group>";
@@ -6177,6 +6183,7 @@
61776183
7B81682A28B6F1420069F315 /* ReactionResponse.swift in Sources */,
61786184
7B7E5B522A4D024C00A8208E /* ExpirationUpdateJob.swift in Sources */,
61796185
FD09799727FFA84A00936362 /* RecipientState.swift in Sources */,
6186+
FDDD554E2C1FCB77006CBF03 /* _019_ScheduleAppUpdateCheckJob.swift in Sources */,
61806187
FDA8EB00280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift in Sources */,
61816188
FD09798927FD1C5A00936362 /* OpenGroup.swift in Sources */,
61826189
FD848B9628422A2A000E298B /* MessageViewModel.swift in Sources */,
@@ -6279,6 +6286,7 @@
62796286
C32C599E256DB02B003C73A2 /* TypingIndicators.swift in Sources */,
62806287
FD716E682850318E00C96BF4 /* CallMode.swift in Sources */,
62816288
FD09799527FE7B8E00936362 /* Interaction.swift in Sources */,
6289+
FDDD554C2C1FC812006CBF03 /* CheckForAppUpdatesJob.swift in Sources */,
62826290
FD37EA0D28AB2A45003AE748 /* _005_FixDeletedMessageReadState.swift in Sources */,
62836291
7BAA7B6628D2DE4700AE1489 /* _009_OpenGroupPermission.swift in Sources */,
62846292
FDC4380927B31D4E00C60D73 /* OpenGroupAPIError.swift in Sources */,
@@ -8034,7 +8042,7 @@
80348042
CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES;
80358043
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
80368044
CODE_SIGN_IDENTITY = "iPhone Developer";
8037-
CURRENT_PROJECT_VERSION = 449;
8045+
CURRENT_PROJECT_VERSION = 452;
80388046
ENABLE_BITCODE = NO;
80398047
ENABLE_STRICT_OBJC_MSGSEND = YES;
80408048
ENABLE_TESTABILITY = YES;
@@ -8071,7 +8079,7 @@
80718079
GCC_WARN_UNUSED_VARIABLE = YES;
80728080
HEADER_SEARCH_PATHS = "";
80738081
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
8074-
MARKETING_VERSION = 2.6.1;
8082+
MARKETING_VERSION = 2.6.2;
80758083
ONLY_ACTIVE_ARCH = YES;
80768084
OTHER_CFLAGS = (
80778085
"-fobjc-arc-exceptions",
@@ -8112,7 +8120,7 @@
81128120
CLANG_WARN__ARC_BRIDGE_CAST_NONARC = YES;
81138121
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
81148122
CODE_SIGN_IDENTITY = "iPhone Distribution";
8115-
CURRENT_PROJECT_VERSION = 449;
8123+
CURRENT_PROJECT_VERSION = 452;
81168124
ENABLE_BITCODE = NO;
81178125
ENABLE_STRICT_OBJC_MSGSEND = YES;
81188126
GCC_NO_COMMON_BLOCKS = YES;
@@ -8144,7 +8152,7 @@
81448152
GCC_WARN_UNUSED_VARIABLE = YES;
81458153
HEADER_SEARCH_PATHS = "";
81468154
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
8147-
MARKETING_VERSION = 2.6.1;
8155+
MARKETING_VERSION = 2.6.2;
81488156
ONLY_ACTIVE_ARCH = NO;
81498157
OTHER_CFLAGS = (
81508158
"-DNS_BLOCK_ASSERTIONS=1",

Session/Meta/AppDelegate.swift

+5-2
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
298298

299299
guard BackgroundPoller.isValid else { return }
300300

301-
Log.info("Background poll failed due to manual timeout")
301+
Log.info("Background poll failed due to manual timeout.")
302302
BackgroundPoller.isValid = false
303303

304304
if Singleton.hasAppContext && Singleton.appContext.isInBackground {
@@ -321,7 +321,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
321321
// the app after this closure is registered but before it's actually triggered - this can
322322
// result in the `BackgroundPoller` incorrectly getting called in the foreground, this check
323323
// is here to prevent that
324-
guard Singleton.hasAppContext && Singleton.appContext.isInBackground else { return }
324+
guard Singleton.hasAppContext && Singleton.appContext.isInBackground else {
325+
BackgroundPoller.isValid = false
326+
return
327+
}
325328

326329
BackgroundPoller.poll { result in
327330
guard BackgroundPoller.isValid else { return }

Session/Utilities/BackgroundPoller.swift

+79-59
Original file line numberDiff line numberDiff line change
@@ -15,46 +15,50 @@ public final class BackgroundPoller {
1515
completionHandler: @escaping (UIBackgroundFetchResult) -> Void,
1616
using dependencies: Dependencies = Dependencies()
1717
) {
18+
let (groupIds, servers): (Set<String>, Set<String>) = Storage.shared.read { db in
19+
(
20+
try ClosedGroup
21+
.select(.threadId)
22+
.joining(
23+
required: ClosedGroup.members
24+
.filter(GroupMember.Columns.profileId == getUserHexEncodedPublicKey(db))
25+
)
26+
.asRequest(of: String.self)
27+
.fetchSet(db),
28+
/// The default room promise creates an OpenGroup with an empty `roomToken` value, we
29+
/// don't want to start a poller for this as the user hasn't actually joined a room
30+
///
31+
/// We also want to exclude any rooms which have failed to poll too many times in a row from
32+
/// the background poll as they are likely to fail again
33+
try OpenGroup
34+
.select(.server)
35+
.filter(
36+
OpenGroup.Columns.roomToken != "" &&
37+
OpenGroup.Columns.isActive &&
38+
OpenGroup.Columns.pollFailureCount < OpenGroupAPI.Poller.maxRoomFailureCountForBackgroundPoll
39+
)
40+
.distinct()
41+
.asRequest(of: String.self)
42+
.fetchSet(db)
43+
)
44+
}
45+
.defaulting(to: ([], []))
46+
47+
Log.info("[BackgroundPoller] Fetching 1 User, \(groupIds.count) \("group", number: groupIds.count), \(servers.count) \("communit", number: servers.count, singular: "y", plural: "ies").")
1848
Publishers
1949
.MergeMany(
2050
[pollForMessages(using: dependencies)]
21-
.appending(contentsOf: pollForClosedGroupMessages(using: dependencies))
22-
.appending(
23-
contentsOf: Storage.shared
24-
.read { db in
25-
/// The default room promise creates an OpenGroup with an empty `roomToken` value, we
26-
/// don't want to start a poller for this as the user hasn't actually joined a room
27-
///
28-
/// We also want to exclude any rooms which have failed to poll too many times in a row from
29-
/// the background poll as they are likely to fail again
30-
try OpenGroup
31-
.select(.server)
32-
.filter(
33-
OpenGroup.Columns.roomToken != "" &&
34-
OpenGroup.Columns.isActive &&
35-
OpenGroup.Columns.pollFailureCount < OpenGroupAPI.Poller.maxRoomFailureCountForBackgroundPoll
36-
)
37-
.distinct()
38-
.asRequest(of: String.self)
39-
.fetchSet(db)
40-
}
41-
.defaulting(to: [])
42-
.map { server -> AnyPublisher<Void, Error> in
43-
let poller: OpenGroupAPI.Poller = OpenGroupAPI.Poller(for: server)
44-
poller.stop()
45-
46-
return poller.poll(
47-
calledFromBackgroundPoller: true,
48-
isBackgroundPollerValid: { BackgroundPoller.isValid },
49-
isPostCapabilitiesRetry: false,
50-
using: dependencies
51-
)
52-
}
53-
)
51+
.appending(contentsOf: pollForClosedGroupMessages(groupIds: groupIds, using: dependencies))
52+
.appending(contentsOf: pollForCommunityMessages(servers: servers, using: dependencies))
5453
)
5554
.subscribe(on: DispatchQueue.global(qos: .background), using: dependencies)
5655
.receive(on: DispatchQueue.main, using: dependencies)
5756
.collect()
57+
.handleEvents(
58+
receiveOutput: { _ in
59+
Log.info("[BackgroundPoller] Finished polling.")
60+
}
61+
)
5862
.sinkUntilComplete(
5963
receiveCompletion: { result in
6064
// If we have already invalidated the timer then do nothing (we essentially timed out)
@@ -63,7 +67,7 @@ public final class BackgroundPoller {
6367
switch result {
6468
case .finished: completionHandler(.newData)
6569
case .failure(let error):
66-
SNLog("Background poll failed due to error: \(error)")
70+
Log.error("[BackgroundPoller] Failed due to error: \(error).")
6771
completionHandler(.failed)
6872
}
6973
}
@@ -83,39 +87,55 @@ public final class BackgroundPoller {
8387
drainBehaviour: .alwaysRandom,
8488
using: dependencies
8589
)
90+
.handleEvents(
91+
receiveOutput: { _, _, validMessageCount, _ in
92+
Log.info("[BackgroundPoller] Received \(validMessageCount) valid \("message", number: validMessageCount).")
93+
}
94+
)
8695
.map { _ in () }
8796
.eraseToAnyPublisher()
8897
}
8998

9099
private static func pollForClosedGroupMessages(
100+
groupIds: Set<String>,
91101
using dependencies: Dependencies
92102
) -> [AnyPublisher<Void, Error>] {
93103
// Fetch all closed groups (excluding any don't contain the current user as a
94104
// GroupMemeber as the user is no longer a member of those)
95-
return Storage.shared
96-
.read { db in
97-
try ClosedGroup
98-
.select(.threadId)
99-
.joining(
100-
required: ClosedGroup.members
101-
.filter(GroupMember.Columns.profileId == getUserHexEncodedPublicKey(db))
102-
)
103-
.asRequest(of: String.self)
104-
.fetchAll(db)
105-
}
106-
.defaulting(to: [])
107-
.map { groupPublicKey in
108-
return ClosedGroupPoller()
109-
.poll(
110-
namespaces: ClosedGroupPoller.namespaces,
111-
for: groupPublicKey,
112-
calledFromBackgroundPoller: true,
113-
isBackgroundPollValid: { BackgroundPoller.isValid },
114-
drainBehaviour: .alwaysRandom,
115-
using: dependencies
116-
)
117-
.map { _ in () }
118-
.eraseToAnyPublisher()
119-
}
105+
return groupIds.map { groupPublicKey in
106+
return ClosedGroupPoller()
107+
.poll(
108+
namespaces: ClosedGroupPoller.namespaces,
109+
for: groupPublicKey,
110+
calledFromBackgroundPoller: true,
111+
isBackgroundPollValid: { BackgroundPoller.isValid },
112+
drainBehaviour: .alwaysRandom,
113+
using: dependencies
114+
)
115+
.handleEvents(
116+
receiveOutput: { _, _, validMessageCount, _ in
117+
Log.info("[BackgroundPoller] Received \(validMessageCount) valid \("message", number: validMessageCount) for group: \(groupPublicKey).")
118+
}
119+
)
120+
.map { _ in () }
121+
.eraseToAnyPublisher()
122+
}
123+
}
124+
125+
private static func pollForCommunityMessages(
126+
servers: Set<String>,
127+
using dependencies: Dependencies
128+
) -> [AnyPublisher<Void, Error>] {
129+
return servers.map { server -> AnyPublisher<Void, Error> in
130+
let poller: OpenGroupAPI.Poller = OpenGroupAPI.Poller(for: server)
131+
poller.stop()
132+
133+
return poller.poll(
134+
calledFromBackgroundPoller: true,
135+
isBackgroundPollerValid: { BackgroundPoller.isValid },
136+
isPostCapabilitiesRetry: false,
137+
using: dependencies
138+
)
139+
}
120140
}
121141
}

SessionMessagingKit/Configuration.swift

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ public enum SNMessagingKit: MigratableTarget { // Just to make the external API
3535
_015_BlockCommunityMessageRequests.self,
3636
_016_MakeBrokenProfileTimestampsNullable.self,
3737
_017_RebuildFTSIfNeeded_2_4_5.self,
38-
_018_DisappearingMessagesConfiguration.self
38+
_018_DisappearingMessagesConfiguration.self,
39+
_019_ScheduleAppUpdateCheckJob.self
3940
]
4041
]
4142
)
@@ -60,5 +61,6 @@ public enum SNMessagingKit: MigratableTarget { // Just to make the external API
6061
JobRunner.setExecutor(ConfigMessageReceiveJob.self, for: .configMessageReceive)
6162
JobRunner.setExecutor(ExpirationUpdateJob.self, for: .expirationUpdate)
6263
JobRunner.setExecutor(GetExpirationJob.self, for: .getExpiration)
64+
JobRunner.setExecutor(CheckForAppUpdatesJob.self, for: .checkForAppUpdates)
6365
}
6466
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright © 2024 Rangeproof Pty Ltd. All rights reserved.
2+
3+
import Foundation
4+
import GRDB
5+
import SessionUtilitiesKit
6+
7+
enum _019_ScheduleAppUpdateCheckJob: Migration {
8+
static let target: TargetMigrations.Identifier = .messagingKit
9+
static let identifier: String = "ScheduleAppUpdateCheckJob" // stringlint:disable
10+
static let needsConfigSync: Bool = false
11+
static let minExpectedRunDuration: TimeInterval = 0.1
12+
static var requirements: [MigrationRequirement] = [.libSessionStateLoaded]
13+
static let fetchedTables: [(TableRecord & FetchableRecord).Type] = []
14+
static let createdOrAlteredTables: [(TableRecord & FetchableRecord).Type] = []
15+
static let droppedTables: [(TableRecord & FetchableRecord).Type] = []
16+
17+
static func migrate(_ db: GRDB.Database) throws {
18+
_ = try Job(
19+
variant: .checkForAppUpdates,
20+
behaviour: .recurring
21+
).migrationSafeInserted(db)
22+
23+
Storage.update(progress: 1, for: self, in: target) // In case this is the last migration
24+
}
25+
}

0 commit comments

Comments
 (0)