|
@ -1200,8 +1200,8 @@ async function bootstrapWatermark(activeDid: string, starredPlanHandleIds: strin |
|
|
`, [mostRecentJwtId, activeDid, mostRecentJwtId]); |
|
|
`, [mostRecentJwtId, activeDid, mostRecentJwtId]); |
|
|
|
|
|
|
|
|
if (result.changes > 0) { |
|
|
if (result.changes > 0) { |
|
|
console.log(`Bootstrap watermark set to: ${mostRecentJwtId}`); |
|
|
console.log(`Bootstrap watermark set to: ${mostRecentJwtId}`); |
|
|
return mostRecentJwtId; |
|
|
return mostRecentJwtId; |
|
|
} else { |
|
|
} else { |
|
|
// Another client already set a newer watermark during bootstrap |
|
|
// Another client already set a newer watermark during bootstrap |
|
|
console.log('Bootstrap skipped: newer watermark already exists'); |
|
|
console.log('Bootstrap skipped: newer watermark already exists'); |
|
@ -2493,8 +2493,8 @@ public class GenericPollingManager { |
|
|
private final Gson gson; |
|
|
private final Gson gson; |
|
|
|
|
|
|
|
|
public GenericPollingManager(Context context, |
|
|
public GenericPollingManager(Context context, |
|
|
DailyNotificationJWTManager jwtManager, |
|
|
DailyNotificationJWTManager jwtManager, |
|
|
DailyNotificationStorage storage) { |
|
|
DailyNotificationStorage storage) { |
|
|
this.context = context; |
|
|
this.context = context; |
|
|
this.jwtManager = jwtManager; |
|
|
this.jwtManager = jwtManager; |
|
|
this.storage = storage; |
|
|
this.storage = storage; |
|
@ -2555,8 +2555,8 @@ public class GenericPollingManager { |
|
|
scheduleWithWorkManager(scheduleId, config); |
|
|
scheduleWithWorkManager(scheduleId, config); |
|
|
|
|
|
|
|
|
return scheduleId; |
|
|
return scheduleId; |
|
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
} catch (Exception e) { |
|
|
Log.e(TAG, "Error scheduling poll: " + e.getMessage(), e); |
|
|
Log.e(TAG, "Error scheduling poll: " + e.getMessage(), e); |
|
|
throw new RuntimeException("Failed to schedule poll", e); |
|
|
throw new RuntimeException("Failed to schedule poll", e); |
|
|
} |
|
|
} |
|
@ -2807,8 +2807,8 @@ class GenericPollingManager { |
|
|
|
|
|
|
|
|
for attempt in 1...maxAttempts { |
|
|
for attempt in 1...maxAttempts { |
|
|
do { |
|
|
do { |
|
|
let (data, response) = try await URLSession.shared.data(for: request) |
|
|
let (data, response) = try await URLSession.shared.data(for: request) |
|
|
|
|
|
|
|
|
guard let httpResponse = response as? HTTPURLResponse else { |
|
|
guard let httpResponse = response as? HTTPURLResponse else { |
|
|
throw NSError(domain: "GenericPollingManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid response type"]) |
|
|
throw NSError(domain: "GenericPollingManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid response type"]) |
|
|
} |
|
|
} |
|
@ -3049,17 +3049,17 @@ export class GenericPollingManager { |
|
|
|
|
|
|
|
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) { |
|
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) { |
|
|
try { |
|
|
try { |
|
|
const response = await fetch(url, { |
|
|
const response = await fetch(url, { |
|
|
method, |
|
|
method, |
|
|
headers, |
|
|
headers, |
|
|
body: JSON.stringify(requestBody) |
|
|
body: JSON.stringify(requestBody) |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
if (!response.ok) { |
|
|
if (!response.ok) { |
|
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`); |
|
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return await response.json(); |
|
|
return await response.json(); |
|
|
|
|
|
|
|
|
} catch (error) { |
|
|
} catch (error) { |
|
|
lastError = error as Error; |
|
|
lastError = error as Error; |
|
@ -3377,8 +3377,8 @@ if (config.genericPolling != null && config.genericPolling.enabled) { |
|
|
for (PollingScheduleConfig<?, ?> scheduleConfig : config.genericPolling.schedules) { |
|
|
for (PollingScheduleConfig<?, ?> scheduleConfig : config.genericPolling.schedules) { |
|
|
CompletableFuture<PollingResult<?>> pollingResult = |
|
|
CompletableFuture<PollingResult<?>> pollingResult = |
|
|
pollingManager.executePoll(scheduleConfig.request, context); |
|
|
pollingManager.executePoll(scheduleConfig.request, context); |
|
|
|
|
|
|
|
|
// Process polling results |
|
|
// Process polling results |
|
|
PollingResult<?> result = pollingResult.get(); |
|
|
PollingResult<?> result = pollingResult.get(); |
|
|
if (result.success && result.data != null) { |
|
|
if (result.success && result.data != null) { |
|
|
// Generate notifications based on result |
|
|
// Generate notifications based on result |
|
@ -3404,8 +3404,8 @@ if let genericPollingConfig = config.genericPolling, genericPollingConfig.enable |
|
|
if result.success, let data = result.data { |
|
|
if result.success, let data = result.data { |
|
|
// Generate notifications based on result |
|
|
// Generate notifications based on result |
|
|
try await generateNotificationsFromPollingResult(result: result, config: scheduleConfig) |
|
|
try await generateNotificationsFromPollingResult(result: result, config: scheduleConfig) |
|
|
} |
|
|
} |
|
|
} catch { |
|
|
} catch { |
|
|
print("Error executing poll: \(error)") |
|
|
print("Error executing poll: \(error)") |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
@ -3454,7 +3454,7 @@ const config: ConfigureOptions = { |
|
|
genericPolling: { |
|
|
genericPolling: { |
|
|
enabled: true, |
|
|
enabled: true, |
|
|
schedules: [ |
|
|
schedules: [ |
|
|
// Starred Projects Polling |
|
|
// Starred Projects Polling |
|
|
{ |
|
|
{ |
|
|
request: starredProjectsRequest, |
|
|
request: starredProjectsRequest, |
|
|
schedule: { |
|
|
schedule: { |
|
@ -3463,7 +3463,7 @@ const config: ConfigureOptions = { |
|
|
maxConcurrentPolls: 1 |
|
|
maxConcurrentPolls: 1 |
|
|
}, |
|
|
}, |
|
|
notificationConfig: { |
|
|
notificationConfig: { |
|
|
enabled: true, |
|
|
enabled: true, |
|
|
templates: { |
|
|
templates: { |
|
|
singleUpdate: '{projectName} has been updated', |
|
|
singleUpdate: '{projectName} has been updated', |
|
|
multipleUpdates: 'You have {count} new updates in your starred projects' |
|
|
multipleUpdates: 'You have {count} new updates in your starred projects' |
|
|