Skip to content

Commit

Permalink
Scheduler: Add result notification to indicate success/failure
Browse files Browse the repository at this point in the history
+ a debug button to quick add test schedules.
  • Loading branch information
d4rken committed Nov 28, 2023
1 parent f9daea7 commit cf080e0
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import eu.darken.sdmse.common.debug.logging.log
import eu.darken.sdmse.common.debug.logging.logTag
import eu.darken.sdmse.common.hasApiLevel
import eu.darken.sdmse.common.notifications.PendingIntentCompat
import eu.darken.sdmse.main.core.SDMTool
import eu.darken.sdmse.main.ui.MainActivity
import javax.inject.Inject

Expand Down Expand Up @@ -53,7 +54,7 @@ class SchedulerNotifications @Inject constructor(
}
}

fun getBuilder(schedule: Schedule?): NotificationCompat.Builder {
private fun getStateBuilder(schedule: Schedule?): NotificationCompat.Builder {
if (schedule == null) {
return builder.apply {
setStyle(null)
Expand All @@ -65,13 +66,13 @@ class SchedulerNotifications @Inject constructor(
return builder.apply {
setContentTitle(context.getString(R.string.scheduler_notification_title))
setContentText(context.getString(R.string.scheduler_notification_message, schedule.label))
log(TAG) { "getBuilder(): $schedule" }
log(TAG) { "getStateBuilder(): $schedule" }
}
}

fun getNotification(schedule: Schedule?): Notification = getBuilder(schedule).build()
private fun getStateNotification(schedule: Schedule?): Notification = getStateBuilder(schedule).build()

fun getForegroundInfo(schedule: Schedule): ForegroundInfo = getBuilder(schedule).toForegroundInfo(schedule)
fun getForegroundInfo(schedule: Schedule): ForegroundInfo = getStateBuilder(schedule).toForegroundInfo(schedule)

private fun NotificationCompat.Builder.toForegroundInfo(schedule: Schedule): ForegroundInfo = if (hasApiLevel(29)) {
@Suppress("NewApi")
Expand All @@ -82,13 +83,13 @@ class SchedulerNotifications @Inject constructor(

private fun ScheduleId.toNotificationid(): Int {
val baseId = (this.hashCode() and Int.MAX_VALUE) % 101
return NOTIFICATION_ID_RANGE + baseId
return NOTIFICATION_ID_RANGE_STATE + baseId
}

fun notify(schedule: Schedule) {
fun notifyState(schedule: Schedule) {
val id = schedule.id.toNotificationid()
val notification = getNotification(schedule)
log(TAG) { "notify($id, $schedule)" }
val notification = getStateNotification(schedule)
log(TAG) { "notifyState($id, $schedule)" }
notificationManager.notify(id, notification)
}

Expand All @@ -98,9 +99,39 @@ class SchedulerNotifications @Inject constructor(
notificationManager.cancel(id)
}

private fun getResultBuilder(results: Set<Results>): NotificationCompat.Builder = builder.apply {
setContentTitle(context.getString(R.string.scheduler_notification_result_title))
val text = if (results.any { it.error != null }) {
context.getString(R.string.scheduler_notification_result_failure_message)
} else {
context.getString(R.string.scheduler_notification_result_success_message)
}
setContentText(text)
log(TAG) { "getResultBuilder(): $results" }
}

private fun Set<Results>.toNotificationid(): Int {
val baseId = (this.hashCode() and Int.MAX_VALUE) % 101
return NOTIFICATION_ID_RANGE_RESULT + baseId
}

fun notifyResult(results: Set<Results>) {
val id = results.toNotificationid()
val notification = getResultBuilder(results).build()
log(TAG) { "notifyResult($id, $results)" }
notificationManager.notify(id, notification)
}

data class Results(
val task: SDMTool.Task,
val result: SDMTool.Task.Result? = null,
val error: Exception? = null,
)

companion object {
val TAG = logTag("Scheduler", "Notifications", "Worker")
private val CHANNEL_ID = "${BuildConfigWrap.APPLICATION_ID}.notification.channel.scheduler"
internal const val NOTIFICATION_ID_RANGE = 1000
internal const val NOTIFICATION_ID_RANGE_STATE = 1000
internal const val NOTIFICATION_ID_RANGE_RESULT = 1200
}
}
25 changes: 15 additions & 10 deletions app/src/main/java/eu/darken/sdmse/scheduler/core/SchedulerWorker.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ import eu.darken.sdmse.systemcleaner.core.tasks.SystemCleanerSchedulerTask
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch


@HiltWorker
Expand All @@ -43,7 +43,7 @@ class SchedulerWorker @AssistedInject constructor(
private val taskManager: TaskManager,
private val schedulerManager: SchedulerManager,
private val schedulerSettings: SchedulerSettings,
private val workerNotifications: SchedulerNotifications,
private val schedulerNotifications: SchedulerNotifications,
private val notificationManager: NotificationManager,
private val setupHealer: SetupHealer,
) : CoroutineWorker(context, params) {
Expand All @@ -63,7 +63,7 @@ class SchedulerWorker @AssistedInject constructor(
}

override suspend fun getForegroundInfo(): ForegroundInfo {
return workerNotifications.getForegroundInfo(getSchedule())
return schedulerNotifications.getForegroundInfo(getSchedule())
}

override suspend fun doWork(): Result = try {
Expand All @@ -75,7 +75,7 @@ class SchedulerWorker @AssistedInject constructor(
log(TAG, INFO) { "Executing schedule $schedule" }
Bugs.leaveBreadCrumb("Executing schedule")

workerNotifications.notify(schedule)
schedulerNotifications.notifyState(schedule)

doDoWork(schedule)

Expand All @@ -97,7 +97,7 @@ class SchedulerWorker @AssistedInject constructor(
Result.success()
}
} finally {
workerNotifications.cancel(scheduleId)
schedulerNotifications.cancel(scheduleId)
workerScope.cancel("Worker finished (withError?=$finishedWithError).")
}

Expand All @@ -124,18 +124,23 @@ class SchedulerWorker @AssistedInject constructor(
.take(1)
.first()

val taskJobs = tasks.map { task ->
workerScope.launch {
val taskJobs = tasks.mapNotNull { task ->
workerScope.async {
try {
taskManager.submit(task)
log(TAG) { "Launching $task" }
val result = taskManager.submit(task)
log(TAG) { "Finished $task -> $result" }
SchedulerNotifications.Results(task, result = result)
} catch (e: Exception) {
log(TAG, ERROR) { "Scheduler task failed ($task): ${e.asLog()}" }
SchedulerNotifications.Results(task, error = e)
}
}
}

log(TAG) { "Waiting for jobs to complete: $taskJobs" }
taskJobs.joinAll()
val taskResults = taskJobs.awaitAll().toSet()
schedulerNotifications.notifyResult(taskResults)
log(TAG) { "All task jobs have finished." }
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.navigation.ui.setupWithNavController
import dagger.hilt.android.AndroidEntryPoint
import eu.darken.sdmse.R
import eu.darken.sdmse.common.WebpageTool
import eu.darken.sdmse.common.debug.Bugs
import eu.darken.sdmse.common.lists.differ.update
import eu.darken.sdmse.common.lists.setupDefaults
import eu.darken.sdmse.common.uix.Fragment3
Expand All @@ -33,9 +34,15 @@ class SchedulerManagerFragment : Fragment3(R.layout.scheduler_manager_fragment)
true
}

R.id.menu_debug_schedule -> {
vm.debugSchedule()
true
}

else -> false
}
}
menu?.findItem(R.id.menu_debug_schedule)?.isVisible = Bugs.isDebug
}

ui.mainAction.setOnClickListener { vm.createNew() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import eu.darken.sdmse.scheduler.core.SchedulerSettings
import eu.darken.sdmse.scheduler.ui.manager.items.AlarmHintRowVH
import eu.darken.sdmse.scheduler.ui.manager.items.ScheduleRowVH
import kotlinx.coroutines.flow.*
import java.time.Duration
import java.time.Instant
import java.time.LocalTime
import java.util.*
import javax.inject.Inject

Expand Down Expand Up @@ -119,6 +121,21 @@ class SchedulerManagerViewModel @Inject constructor(
).navigate()
}

fun debugSchedule() = launch {
log(TAG) { "debugSchedule()" }
val id = UUID.randomUUID().toString()
val now = LocalTime.now().plusMinutes(1)
val testSchedule = Schedule(
id = id,
label = "Test Schedule $id",
hour = now.hour,
minute = now.minute,
repeatInterval = Duration.ofDays(1),
scheduledAt = Instant.now(),
)
schedulerManager.saveSchedule(testSchedule)
}

data class State(
val listItems: List<SchedulerAdapter.Item>? = null,
)
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/res/layout/scheduler_manager_fragment.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/menu_data_areas"
app:menu="@menu/menu_scheduler_manager"
app:title="@string/scheduler_label" />

<eu.darken.sdmse.common.progress.ProgressOverlayView
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/res/menu/menu_scheduler_manager.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@
<!-- app:showAsAction="ifRoom"-->
<!-- tools:visible="true" />-->

<item
android:id="@+id/menu_debug_schedule"
android:icon="@drawable/ic_play_arrow"
android:orderInCategory="90"
android:title="Launch schedule now"
android:visible="false"
app:showAsAction="ifRoom" />

<item
android:id="@+id/menu_action_info"
android:icon="@drawable/ic_baseline_info_24"
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -578,6 +578,9 @@
<string name="scheduler_notification_channel_label">Scheduler</string>
<string name="scheduler_notification_title">Scheduled task</string>
<string name="scheduler_notification_message">Executing: \"%s\"</string>
<string name="scheduler_notification_result_title">Scheduler finished</string>
<string name="scheduler_notification_result_success_message">All scheduled tasks ran successfully.</string>
<string name="scheduler_notification_result_failure_message">Some scheduled tasks failed or encountered errors. Try running them manually.</string>

<string name="updates_dashcard_title">Update available</string>
<string name="updates_dashcard_body">An update is available. You have %1$s and the latest version is %2$s.</string>
Expand Down

0 comments on commit cf080e0

Please sign in to comment.