From cdc393003694892e86fb654bab700c6fbe50d39c Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 6 Apr 2018 16:38:56 -0500 Subject: [PATCH 1/2] Do not allow task to run if part of a group and not the first task in the group. --- .../PendingTasksRecyclerViewAdapter.kt | 8 +- .../java/com/levibostian/wendy/WendyConfig.kt | 4 + .../wendy/db/PendingTasksManager.kt | 19 ++++ .../wendy/extension/PendingTaskExtensions.kt | 16 +++ .../listeners/PendingTaskStatusListener.kt | 2 +- .../levibostian/wendy/service/PendingTask.kt | 2 +- .../wendy/service/PendingTasksRunner.kt | 5 +- .../com/levibostian/wendy/service/Wendy.kt | 98 ++++++++++++++++--- .../wendy/types/ReasonPendingTaskSkipped.kt | 2 +- 9 files changed, 137 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/com/levibostian/wendyexample/PendingTasksRecyclerViewAdapter.kt b/app/src/main/java/com/levibostian/wendyexample/PendingTasksRecyclerViewAdapter.kt index 2018b5a..1683921 100644 --- a/app/src/main/java/com/levibostian/wendyexample/PendingTasksRecyclerViewAdapter.kt +++ b/app/src/main/java/com/levibostian/wendyexample/PendingTasksRecyclerViewAdapter.kt @@ -9,6 +9,9 @@ import android.widget.Button import android.widget.TextView import com.curiosityio.wendyexample.R import com.levibostian.wendy.WendyConfig +import com.levibostian.wendy.extension.addTaskStatusListenerForTask +import com.levibostian.wendy.extension.doesErrorExist +import com.levibostian.wendy.extension.isAbleToManuallyRun import com.levibostian.wendy.service.PendingTask import com.levibostian.wendy.service.Wendy import java.text.SimpleDateFormat @@ -48,12 +51,13 @@ class PendingTasksRecyclerViewAdapter(val data: List) : RecyclerVie holder.createdAtTextView.text = String.format("Created: %s", SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z", Locale.ENGLISH).format(adapterItem.createdAt)) holder.statusTextView.text = "not running" - WendyConfig.addTaskStatusListenerForTask(adapterItem.taskId!!, holder.statusTextView) + adapterItem.addTaskStatusListenerForTask(holder.statusTextView) + holder.runTaskButton.visibility = if (adapterItem.isAbleToManuallyRun()) View.VISIBLE else View.GONE holder.runTaskButton.setOnClickListener { listener?.manuallyRunPressed(adapterItem) } - holder.resolveErrorButton.visibility = if (Wendy.shared.doesErrorExist(adapterItem.taskId!!)) View.VISIBLE else View.GONE + holder.resolveErrorButton.visibility = if (adapterItem.doesErrorExist()) View.VISIBLE else View.GONE holder.resolveErrorButton.setOnClickListener { listener?.resolveErrorPressed(adapterItem) } diff --git a/wendy/src/main/java/com/levibostian/wendy/WendyConfig.kt b/wendy/src/main/java/com/levibostian/wendy/WendyConfig.kt index c2d5697..8cbf8a7 100644 --- a/wendy/src/main/java/com/levibostian/wendy/WendyConfig.kt +++ b/wendy/src/main/java/com/levibostian/wendy/WendyConfig.kt @@ -28,6 +28,10 @@ class WendyConfig { /** * Sets Wendy to strict mode or not. Strict mode helps while developing your app to find and fix potential issues while working with Wendy. * + * Strict mode is **only** used in scenarios that a warning is not critical to the success of your app. How success if defined here is: (1) Your user does not get confused when they perform an action in your app and the request is simply ignored resulting in them being confused and (2) your app crashing only when you have hit a major issue that you really should fix (wendy cannot work without you fixing these crashes). + * + * Wendy **does** still throw exceptions. Strict mode does *not* silence all exceptions. Strict simply gives you the option to silence warnings when it's really not a big deal that your code works in a certain way. It's assumed you know what you are doing. + * * When strict is true, warnings throw errors instead of logging the warning to the console. * When strict is false, warnings get logged to the console and not crash your app instead. * diff --git a/wendy/src/main/java/com/levibostian/wendy/db/PendingTasksManager.kt b/wendy/src/main/java/com/levibostian/wendy/db/PendingTasksManager.kt index 4e49ca4..7911282 100644 --- a/wendy/src/main/java/com/levibostian/wendy/db/PendingTasksManager.kt +++ b/wendy/src/main/java/com/levibostian/wendy/db/PendingTasksManager.kt @@ -44,6 +44,25 @@ internal class PendingTasksManager(context: Context) { } } + /** + * @throws IllegalArgumentException if task by taskId does not exist. + * @throws IllegalArgumentException if task by taskId does not belong to any groups. + */ + @Synchronized + internal fun isTaskFirstTaskOfGroup(taskId: Long): Boolean { + val pendingTask = getTaskByTaskId(taskId) ?: throw IllegalArgumentException("Task with id: $taskId does not exist.") + if (pendingTask.groupId == null) throw IllegalArgumentException("Task: $pendingTask does not belong to a group.") + + return db.use { + select(PersistedPendingTask.TABLE_NAME) + .whereArgs("(${PersistedPendingTask.COLUMN_GROUP_ID} = ${pendingTask.groupId})") + .exec { + val tasksInGroup: List = parseList(classParser()) + tasksInGroup[0].id == taskId + } + } + } + /** * Note: It's assumed that you have checked if the PendingTaskError.taskId exists. */ diff --git a/wendy/src/main/java/com/levibostian/wendy/extension/PendingTaskExtensions.kt b/wendy/src/main/java/com/levibostian/wendy/extension/PendingTaskExtensions.kt index 4b5ab4d..ec5a476 100644 --- a/wendy/src/main/java/com/levibostian/wendy/extension/PendingTaskExtensions.kt +++ b/wendy/src/main/java/com/levibostian/wendy/extension/PendingTaskExtensions.kt @@ -36,6 +36,22 @@ fun PendingTask.getLatestError(): PendingTaskError? { return Wendy.shared.getLatestError(taskId) } +/** + * Extension to [Wendy.doesErrorExist] easily from a [PendingTask] instance. + */ +fun PendingTask.doesErrorExist(): Boolean { + val taskId = assertHasBeenAddedToWendy() + return Wendy.shared.doesErrorExist(taskId) +} + +/** + * Extension to [Wendy.isTaskAbleToManuallyRun] easily from a [PendingTask] instance. + */ +fun PendingTask.isAbleToManuallyRun(): Boolean { + val taskId = assertHasBeenAddedToWendy() + return Wendy.shared.isTaskAbleToManuallyRun(taskId) +} + /** * Extension to [WendyConfig.addTaskStatusListenerForTask] easily from a [PendingTask] instance. */ diff --git a/wendy/src/main/java/com/levibostian/wendy/listeners/PendingTaskStatusListener.kt b/wendy/src/main/java/com/levibostian/wendy/listeners/PendingTaskStatusListener.kt index aa985e9..9c6a8ca 100644 --- a/wendy/src/main/java/com/levibostian/wendy/listeners/PendingTaskStatusListener.kt +++ b/wendy/src/main/java/com/levibostian/wendy/listeners/PendingTaskStatusListener.kt @@ -57,5 +57,5 @@ interface PendingTaskStatusListener { * * @see ReasonPendingTaskSkipped for all available reasons why a [PendingTask] was skipped. */ - @UiThread fun skipped(taskId: Long, reason: ReasonPendingTaskSkipped) // Currently, the only reason a pending task is skipped is if the task `canRunTask()` returns false. There is currently no way to determine if it's because of a group id skip. + @UiThread fun skipped(taskId: Long, reason: ReasonPendingTaskSkipped) // Currently, the only reason a pending task is skipped is if the task `isReadyToRun()` returns false. There is currently no way to determine if it's because of a group id skip. } \ No newline at end of file diff --git a/wendy/src/main/java/com/levibostian/wendy/service/PendingTask.kt b/wendy/src/main/java/com/levibostian/wendy/service/PendingTask.kt index 0d79031..30ef586 100644 --- a/wendy/src/main/java/com/levibostian/wendy/service/PendingTask.kt +++ b/wendy/src/main/java/com/levibostian/wendy/service/PendingTask.kt @@ -43,7 +43,7 @@ abstract class PendingTask(override var manuallyRun: Boolean, /** * Override this to dynamically set if this task is ready to run or not. */ - open fun canRunTask(): Boolean = true + open fun isReadyToRun(): Boolean = true /** * Use to go from [PersistedPendingTask] to [PendingTask] after running a SQLite query. diff --git a/wendy/src/main/java/com/levibostian/wendy/service/PendingTasksRunner.kt b/wendy/src/main/java/com/levibostian/wendy/service/PendingTasksRunner.kt index 6910e1b..09617c2 100644 --- a/wendy/src/main/java/com/levibostian/wendy/service/PendingTasksRunner.kt +++ b/wendy/src/main/java/com/levibostian/wendy/service/PendingTasksRunner.kt @@ -64,13 +64,16 @@ internal class PendingTasksRunner(val context: Context, }) } + /** + * @throws [RuntimeException] when in [WendyConfig.strict] mode and you say that your [PendingTask] was [PendingTaskResult.SUCCESSFUL] when you have an unresolved error recorded for that [PendingTask]. + */ @Synchronized @WorkerThread fun runTask(taskId: Long): PendingTasksRunnerJobRunResult { val persistedPendingTaskId: Long = pendingTasksManager.getTaskByTaskId(taskId)?.id ?: return PendingTasksRunnerJobRunResult.SKIPPED_TASK_DOESNT_EXIST val taskToRun: PendingTask = pendingTasksManager.getPendingTaskTaskById(taskId)!! - if (!taskToRun.canRunTask()) { + if (!taskToRun.isReadyToRun()) { WendyConfig.logTaskSkipped(taskToRun, ReasonPendingTaskSkipped.NOT_READY_TO_RUN) LogUtil.d("Task: $taskToRun is not ready to run. Skipping it.") return PendingTasksRunnerJobRunResult.SKIPPED_NOT_READY diff --git a/wendy/src/main/java/com/levibostian/wendy/service/Wendy.kt b/wendy/src/main/java/com/levibostian/wendy/service/Wendy.kt index 87e9c83..164be4b 100644 --- a/wendy/src/main/java/com/levibostian/wendy/service/Wendy.kt +++ b/wendy/src/main/java/com/levibostian/wendy/service/Wendy.kt @@ -6,6 +6,7 @@ import com.evernote.android.job.JobManager import com.levibostian.wendy.WendyConfig import com.levibostian.wendy.db.PendingTaskError import com.levibostian.wendy.db.PendingTasksManager +import com.levibostian.wendy.db.PersistedPendingTask import com.levibostian.wendy.job.PendingTaskJobCreator import com.levibostian.wendy.job.PendingTasksJob import com.levibostian.wendy.listeners.PendingTaskStatusListener @@ -13,6 +14,7 @@ import com.levibostian.wendy.listeners.TaskRunnerListener import com.levibostian.wendy.logErrorRecorded import com.levibostian.wendy.logErrorResolved import com.levibostian.wendy.logNewTaskAdded +import com.levibostian.wendy.types.PendingTaskResult import com.levibostian.wendy.util.LogUtil /** @@ -108,20 +110,41 @@ class Wendy private constructor(context: Context, internal val tasksFactory: Pen val addedTask = tasksManager.insertPendingTask(pendingTask) WendyConfig.logNewTaskAdded(addedTask) - if (WendyConfig.automaticallyRunTasks && !addedTask.manuallyRun) { - LogUtil.d("Wendy is configured to automatically run tasks. Wendy will now attempt to run newly added task: $addedTask") - runTask(addedTask.taskId!!) // Run task right now in case this newly added task can run right away. - } else LogUtil.d("Wendy configured to not automatically run tasks. Skipping execution of newly added task: $addedTask") + runTaskIfAbleTo(addedTask) return addedTask.taskId!! } + /** + * Note: This function is for internal use only. There are no checks to make sure that it exists and stuff. It's assumed you know what you're doing. + */ + private fun runTaskIfAbleTo(pendingTask: PendingTask): Boolean { + if (!WendyConfig.automaticallyRunTasks) { + LogUtil.d("Wendy configured to not automatically run tasks. Skipping execution of newly added task: $pendingTask") + return false + } + if (pendingTask.manuallyRun) { + LogUtil.d("Task is set to manually run. Skipping execution of newly added task: $pendingTask") + return false + } + if (isTaskAbleToManuallyRun(pendingTask.taskId!!)) { + LogUtil.d("Task is not able to manually run. Skipping execution of newly added task: $pendingTask") + return false + } + + LogUtil.d("Wendy is configured to automatically run tasks. Wendy will now attempt to run newly added task: $pendingTask") + runTask(pendingTask.taskId!!) + + return true + } + /** * Manually run all pending tasks. Wendy takes care of running this periodically for you, but you can manually run tasks here. * * *Note:* This will run all tasks even if you use [WendyConfig.automaticallyRunTasks] to enable/disable running of all the [PendingTask]s. * * @param groupId Limit running of the tasks to only tasks of this specific group id. + * @throws [RuntimeException] when in [WendyConfig.strict] mode and you say that your [PendingTask] was [PendingTaskResult.SUCCESSFUL] when you have an unresolved error recorded for that [PendingTask]. */ fun runTasks(groupId: String? = null) { PendingTasksRunner.PendingTasksRunnerAllTasksAsyncTask(runner, tasksManager).execute(PendingTasksRunner.RunAllTasksFilter(groupId)) @@ -130,14 +153,61 @@ class Wendy private constructor(context: Context, internal val tasksFactory: Pen /** * Use this function along with manually run tasks to have Wendy run it for you. If it is successful, Wendy will take care of deleting it for you. * - * @param taskId The [PendingTask.taskId] of [PendingTask] you wish to run. If there is not a [PendingTask] with this ID, the task runner simply ignores your request and moves on. + * @param taskId The [PendingTask.taskId] of [PendingTask] you wish to run. + * + * @throws [IllegalArgumentException] If the [PendingTask] for the taskId provided does not exist. + * @throws [RuntimeException] If the [PendingTask] returns false for [isTaskAbleToManuallyRun]. * * @see [WendyConfig.addTaskStatusListenerForTask] to learn how to listen to the status of a task that you have set to run. */ fun runTask(taskId: Long) { + val pendingTask: PendingTask = assertPendingTaskExists(taskId) + + if (!isTaskAbleToManuallyRun(taskId)) { + throw RuntimeException("Task is not able to manually run. Task: $pendingTask") + } + PendingTasksRunner.PendingTasksRunnerGivenSetTasksAsyncTask(runner).execute(taskId) } + /** + * Tells you if a [PendingTask] is able to run yet or not. + * + * To be able to run, all of these must be true: + * 1. A [PendingTask] is not part of a group or it is the first task of a group. + * + * Call this before calling [runTask] to avoid [runTask] throwing an exception on you for it not being ready to run. + * + * @throws [IllegalArgumentException] If the [PendingTask] for the taskId provided does not exist. + */ + fun isTaskAbleToManuallyRun(taskId: Long): Boolean { + val pendingTask: PendingTask = assertPendingTaskExists(taskId) + + if (pendingTask.groupId == null) return true + return tasksManager.isTaskFirstTaskOfGroup(taskId) + } + + /** + * Checks to make sure that a [PendingTask] does exist in the database, else throw an exception. + * + * Why throw an exception? I used to simply ignore your request if you called a function such as [recordError] if you gave a taskId parameter for a task that did not exist in the database. But I decided to remove that because [PendingTask] should always be found in the database unless one of the following happens: + * + * 1. You did not add the [PendingTask] to the database in the first place which you should get an exception thrown on you then to make sure you fix that. + * 2. The [PendingTask] previously existed, but the task ran successfully and the task runner deleted. In that case, you *should* not be doing actions such as trying to record errors then, right? You should have returns [PendingTaskResult.FAILED] instead which will not delete your task. + * + * You do not need to use this function. But you should use it if there is a scenario when a [PendingTask] could be deleted and your code tries to perform an action on it. Race conditions are real and we do keep them in mind. But if your code *should* be following best practices, then we should throw exceptions instead to get you to fix your code. + */ + internal fun assertPendingTaskExists(taskId: Long): PendingTask { + return tasksManager.getPendingTaskTaskById(taskId) ?: throw IllegalArgumentException("Task with id: $taskId does not exist.") + } + + /** + * @see [assertPendingTaskExists] + */ + internal fun assertPersistedPendingTaskExists(taskId: Long): PersistedPendingTask { + return tasksManager.getTaskByTaskId(taskId) ?: throw IllegalArgumentException("Task with id: $taskId does not exist.") + } + /** * If you, for some reason, wish to receive a copy of all the [PendingTask] instances that still need to run successfully by Wendy, here is how you get them. */ @@ -148,14 +218,14 @@ class Wendy private constructor(context: Context, internal val tasksFactory: Pen /** * If you encounter an error while executing [PendingTask.runTask] in one of your [PendingTask]s, you can record it here to handle later in your app. This is usually used when your [PendingTask] encounters an error that requires the app user to fix (example: A string sent up to your API is too long. The user must shorten it up). * - * *Note:* If you attempt to record an error using a [taskId] that does not exist, your request to record an error will be ignored. - * * @param taskId The [PendingTask.taskId] for the [PendingTask] that encountered an error. * @param humanReadableErrorMessage A human readable error message that you may choose to show in the UI of your app. This message describes the error to the end user. Make sure they can understand it so they can resolve their issue. * @param errorId An ID identifying this error to Wendy. This exists for you, the developer. If and when the user of your app decides to fix the error, you can use this ID to determine what it was that was broken so you can show a UI to the user to fix the issue. Example: An `errorId` of "CreateGroceryItem" in your app could map to a UI in your app that shows the text of the entered grocery store item and the option for your user to edit it. + * + * @throws [IllegalArgumentException] If the [PendingTask] for the taskId provided does not exist. This should only happen if you (1) never added the [PendingTask] to Wendy in the first place or (2) the [PendingTask] ran, and was successful (then you should never have recorded an error in the first place). */ fun recordError(taskId: Long, humanReadableErrorMessage: String?, errorId: String?) { - val pendingTask = tasksManager.getPendingTaskTaskById(taskId) ?: return + val pendingTask: PendingTask = assertPendingTaskExists(taskId) tasksManager.insertPendingTaskError(PendingTaskError.init(taskId, humanReadableErrorMessage, errorId)) @@ -166,9 +236,11 @@ class Wendy private constructor(context: Context, internal val tasksFactory: Pen * How to check if an error has been recorded for a [PendingTask]. * * @param taskId The taskId of a [PendingTask] you may or may not have recorded an error for. + * + * @throws [IllegalArgumentException] If the [PendingTask] for the taskId provided does not exist. */ fun getLatestError(taskId: Long): PendingTaskError? { - val pendingTask = tasksManager.getPendingTaskTaskById(taskId) ?: return null + val pendingTask: PendingTask = assertPendingTaskExists(taskId) val pendingTaskError = tasksManager.getLatestError(taskId) pendingTaskError?.pendingTask = pendingTask @@ -184,8 +256,6 @@ class Wendy private constructor(context: Context, internal val tasksFactory: Pen /** * Mark a previously recorded error for a [PendingTask] as resolved. * - * *Note:* If you attempt to resolve an error using a [taskId] that does not exist, your request to record an error will be ignored. - * * *Note:* If you attempt to resolve an error when an error does not exist in Wendy (because it has already been resolved or was never recorded) then the [TaskRunnerListener.errorResolved] and [PendingTaskStatusListener.errorResolved] will not be called. * * *Note:* The task runner will attempt to run your task after it has been resolved immediately. If the task belongs to a group, the task runner will attempt to run all the tasks in the group. @@ -193,10 +263,12 @@ class Wendy private constructor(context: Context, internal val tasksFactory: Pen * @param taskId The taskId of a [PendingTask] previously recorded an error for. * @return If [PendingTask] had a previously recorded error and it has been marked as resolved now. * + * @throws [IllegalArgumentException] If the [PendingTask] for the taskId provided does not exist. + * * @see recordError This is how to record an error. */ fun resolveError(taskId: Long): Boolean { - val pendingTask = tasksManager.getPendingTaskTaskById(taskId) ?: return false + val pendingTask: PendingTask = assertPendingTaskExists(taskId) if (tasksManager.deletePendingTaskError(taskId)) { // Only log error as resolved if an error was even recorded in the first place. WendyConfig.logErrorResolved(pendingTask) @@ -204,7 +276,7 @@ class Wendy private constructor(context: Context, internal val tasksFactory: Pen val groupId: String? = pendingTask.groupId if (groupId != null) runTasks(groupId) - else runTask(taskId) + else runTaskIfAbleTo(pendingTask) return true } diff --git a/wendy/src/main/java/com/levibostian/wendy/types/ReasonPendingTaskSkipped.kt b/wendy/src/main/java/com/levibostian/wendy/types/ReasonPendingTaskSkipped.kt index 033b876..01fbeac 100644 --- a/wendy/src/main/java/com/levibostian/wendy/types/ReasonPendingTaskSkipped.kt +++ b/wendy/src/main/java/com/levibostian/wendy/types/ReasonPendingTaskSkipped.kt @@ -11,7 +11,7 @@ enum class ReasonPendingTaskSkipped { /** * The [PendingTask] of the app said that it was not ready to run. * - * @see PendingTask.canRunTask to learn how your app can indicate if it's able to run or not at runtime. + * @see PendingTask.isReadyToRun to learn how your app can indicate if it's able to run or not at runtime. */ NOT_READY_TO_RUN { /** From b3d30ac78e935f1a9d5486d86f928379516a6629 Mon Sep 17 00:00:00 2001 From: Levi Bostian Date: Fri, 6 Apr 2018 16:48:52 -0500 Subject: [PATCH 2/2] Generate docs. Add generate output to Dangerfile to make sure no warnings. --- Dangerfile | 7 +++- bin/pr-tasks.sh | 1 - .../does-error-exist.html | 15 ++++++++ .../index.html | 18 ++++++++++ .../is-able-to-manually-run.html | 15 ++++++++ .../-pending-task/index.html | 36 ++++++++++++++----- .../-pending-task/is-ready-to-run.html | 15 ++++++++ .../-wendy/get-latest-error.html | 3 ++ .../-wendy/index.html | 9 +++++ .../-wendy/is-task-able-to-manually-run.html | 22 ++++++++++++ .../-wendy/record-error.html | 4 ++- .../-wendy/resolve-error.html | 4 ++- .../-wendy/run-task.html | 7 +++- .../-wendy/run-tasks.html | 3 ++ .../-n-o-t_-r-e-a-d-y_-t-o_-r-u-n/index.html | 2 +- .../-wendy-config/strict.html | 2 ++ docs/wendy/index-outline.html | 8 +++-- 17 files changed, 154 insertions(+), 17 deletions(-) create mode 100644 docs/wendy/com.levibostian.wendy.extension/does-error-exist.html create mode 100644 docs/wendy/com.levibostian.wendy.extension/is-able-to-manually-run.html create mode 100644 docs/wendy/com.levibostian.wendy.service/-pending-task/is-ready-to-run.html create mode 100644 docs/wendy/com.levibostian.wendy.service/-wendy/is-task-able-to-manually-run.html diff --git a/Dangerfile b/Dangerfile index 4a70d56..8d380c1 100644 --- a/Dangerfile +++ b/Dangerfile @@ -6,4 +6,9 @@ end if git.modified_files.include? "build.gradle" or git.modified_files.include? "wendy/build.gradle" warn "I see you edited a `build.gradle` file. Keep in mind that unless you are simply upgrading version numbers of libraries, that is ok. If you are adding dependencies, you may get your PR denied to keep the library slim." -end \ No newline at end of file +end + +# Generate the dokka docs and output the docs to the PR to assert there are no warnings. +`./bin/install_android_sdk.sh` +generateDocsOutput = `./gradlew dokka` +markdown "Output of generating docs: \n ```#{generateDocsOutput}```" diff --git a/bin/pr-tasks.sh b/bin/pr-tasks.sh index 7803b99..8dd8435 100755 --- a/bin/pr-tasks.sh +++ b/bin/pr-tasks.sh @@ -2,6 +2,5 @@ set -e -./gradlew dokka ./gradlew assembleDebug ./gradlew test diff --git a/docs/wendy/com.levibostian.wendy.extension/does-error-exist.html b/docs/wendy/com.levibostian.wendy.extension/does-error-exist.html new file mode 100644 index 0000000..7ec5dba --- /dev/null +++ b/docs/wendy/com.levibostian.wendy.extension/does-error-exist.html @@ -0,0 +1,15 @@ + + + +doesErrorExist - wendy + + + +wendy / com.levibostian.wendy.extension / doesErrorExist
+
+

doesErrorExist

+ +fun PendingTask.doesErrorExist(): Boolean +

Extension to Wendy.doesErrorExist easily from a PendingTask instance.

+ + diff --git a/docs/wendy/com.levibostian.wendy.extension/index.html b/docs/wendy/com.levibostian.wendy.extension/index.html index cbcabdf..b6e2133 100644 --- a/docs/wendy/com.levibostian.wendy.extension/index.html +++ b/docs/wendy/com.levibostian.wendy.extension/index.html @@ -22,6 +22,15 @@

Functions

+

doesErrorExist

+ + +fun PendingTask.doesErrorExist(): Boolean +

Extension to Wendy.doesErrorExist easily from a PendingTask instance.

+ + + +

getLatestError

@@ -40,6 +49,15 @@

Functions

+

isAbleToManuallyRun

+ + +fun PendingTask.isAbleToManuallyRun(): Boolean +

Extension to Wendy.isTaskAbleToManuallyRun easily from a PendingTask instance.

+ + + +

recordError

diff --git a/docs/wendy/com.levibostian.wendy.extension/is-able-to-manually-run.html b/docs/wendy/com.levibostian.wendy.extension/is-able-to-manually-run.html new file mode 100644 index 0000000..58c3e8c --- /dev/null +++ b/docs/wendy/com.levibostian.wendy.extension/is-able-to-manually-run.html @@ -0,0 +1,15 @@ + + + +isAbleToManuallyRun - wendy + + + +wendy / com.levibostian.wendy.extension / isAbleToManuallyRun
+
+

isAbleToManuallyRun

+ +fun PendingTask.isAbleToManuallyRun(): Boolean +

Extension to Wendy.isTaskAbleToManuallyRun easily from a PendingTask instance.

+ + diff --git a/docs/wendy/com.levibostian.wendy.service/-pending-task/index.html b/docs/wendy/com.levibostian.wendy.service/-pending-task/index.html index f0e1c34..259b1e8 100644 --- a/docs/wendy/com.levibostian.wendy.service/-pending-task/index.html +++ b/docs/wendy/com.levibostian.wendy.service/-pending-task/index.html @@ -89,15 +89,6 @@

Functions

-

canRunTask

- - -open fun canRunTask(): Boolean -

Override this to dynamically set if this task is ready to run or not.

- - - -

equals

@@ -116,6 +107,15 @@

Functions

+

isReadyToRun

+ + +open fun isReadyToRun(): Boolean +

Override this to dynamically set if this task is ready to run or not.

+ + + +

runTask

@@ -148,6 +148,15 @@

Extension Functions

+

doesErrorExist

+ + +fun PendingTask.doesErrorExist(): Boolean +

Extension to Wendy.doesErrorExist easily from a PendingTask instance.

+ + + +

getLatestError

@@ -166,6 +175,15 @@

Extension Functions

+

isAbleToManuallyRun

+ + +fun PendingTask.isAbleToManuallyRun(): Boolean +

Extension to Wendy.isTaskAbleToManuallyRun easily from a PendingTask instance.

+ + + +

recordError

diff --git a/docs/wendy/com.levibostian.wendy.service/-pending-task/is-ready-to-run.html b/docs/wendy/com.levibostian.wendy.service/-pending-task/is-ready-to-run.html new file mode 100644 index 0000000..299296a --- /dev/null +++ b/docs/wendy/com.levibostian.wendy.service/-pending-task/is-ready-to-run.html @@ -0,0 +1,15 @@ + + + +PendingTask.isReadyToRun - wendy + + + +wendy / com.levibostian.wendy.service / PendingTask / isReadyToRun
+
+

isReadyToRun

+ +open fun isReadyToRun(): Boolean +

Override this to dynamically set if this task is ready to run or not.

+ + diff --git a/docs/wendy/com.levibostian.wendy.service/-wendy/get-latest-error.html b/docs/wendy/com.levibostian.wendy.service/-wendy/get-latest-error.html index 1f55f5a..15085e3 100644 --- a/docs/wendy/com.levibostian.wendy.service/-wendy/get-latest-error.html +++ b/docs/wendy/com.levibostian.wendy.service/-wendy/get-latest-error.html @@ -14,5 +14,8 @@

getLatestError

Parameters

taskId - The taskId of a PendingTask you may or may not have recorded an error for.

+

Exceptions

+

+IllegalArgumentException - If the PendingTask for the taskId provided does not exist.

diff --git a/docs/wendy/com.levibostian.wendy.service/-wendy/index.html b/docs/wendy/com.levibostian.wendy.service/-wendy/index.html index 09c0316..0c620c2 100644 --- a/docs/wendy/com.levibostian.wendy.service/-wendy/index.html +++ b/docs/wendy/com.levibostian.wendy.service/-wendy/index.html @@ -69,6 +69,15 @@

Functions

+

isTaskAbleToManuallyRun

+ + +fun isTaskAbleToManuallyRun(taskId: Long): Boolean +

Tells you if a PendingTask is able to run yet or not.

+ + + +

recordError

diff --git a/docs/wendy/com.levibostian.wendy.service/-wendy/is-task-able-to-manually-run.html b/docs/wendy/com.levibostian.wendy.service/-wendy/is-task-able-to-manually-run.html new file mode 100644 index 0000000..351bb90 --- /dev/null +++ b/docs/wendy/com.levibostian.wendy.service/-wendy/is-task-able-to-manually-run.html @@ -0,0 +1,22 @@ + + + +Wendy.isTaskAbleToManuallyRun - wendy + + + +wendy / com.levibostian.wendy.service / Wendy / isTaskAbleToManuallyRun
+
+

isTaskAbleToManuallyRun

+ +fun isTaskAbleToManuallyRun(taskId: Long): Boolean +

Tells you if a PendingTask is able to run yet or not.

+

To be able to run, all of these must be true:

+
  1. A PendingTask is not part of a group or it is the first task of a group.
  2. +
+

Call this before calling runTask to avoid runTask throwing an exception on you for it not being ready to run.

+

Exceptions

+

+IllegalArgumentException - If the PendingTask for the taskId provided does not exist.

+ + diff --git a/docs/wendy/com.levibostian.wendy.service/-wendy/record-error.html b/docs/wendy/com.levibostian.wendy.service/-wendy/record-error.html index b7d6da9..bd989f6 100644 --- a/docs/wendy/com.levibostian.wendy.service/-wendy/record-error.html +++ b/docs/wendy/com.levibostian.wendy.service/-wendy/record-error.html @@ -11,7 +11,6 @@

recordError

fun recordError(taskId: Long, humanReadableErrorMessage: String?, errorId: String?): Unit

If you encounter an error while executing PendingTask.runTask in one of your PendingTasks, you can record it here to handle later in your app. This is usually used when your PendingTask encounters an error that requires the app user to fix (example: A string sent up to your API is too long. The user must shorten it up).

-

Note: If you attempt to record an error using a taskId that does not exist, your request to record an error will be ignored.

Parameters

taskId - The PendingTask.taskId for the PendingTask that encountered an error.

@@ -19,5 +18,8 @@

Parameters

humanReadableErrorMessage - A human readable error message that you may choose to show in the UI of your app. This message describes the error to the end user. Make sure they can understand it so they can resolve their issue.

errorId - An ID identifying this error to Wendy. This exists for you, the developer. If and when the user of your app decides to fix the error, you can use this ID to determine what it was that was broken so you can show a UI to the user to fix the issue. Example: An errorId of "CreateGroceryItem" in your app could map to a UI in your app that shows the text of the entered grocery store item and the option for your user to edit it.

+

Exceptions

+

+IllegalArgumentException - If the PendingTask for the taskId provided does not exist. This should only happen if you (1) never added the PendingTask to Wendy in the first place or (2) the PendingTask ran, and was successful (then you should never have recorded an error in the first place).

diff --git a/docs/wendy/com.levibostian.wendy.service/-wendy/resolve-error.html b/docs/wendy/com.levibostian.wendy.service/-wendy/resolve-error.html index 1e9b12f..5bef112 100644 --- a/docs/wendy/com.levibostian.wendy.service/-wendy/resolve-error.html +++ b/docs/wendy/com.levibostian.wendy.service/-wendy/resolve-error.html @@ -11,12 +11,14 @@

resolveError

fun resolveError(taskId: Long): Boolean

Mark a previously recorded error for a PendingTask as resolved.

-

Note: If you attempt to resolve an error using a taskId that does not exist, your request to record an error will be ignored.

Note: If you attempt to resolve an error when an error does not exist in Wendy (because it has already been resolved or was never recorded) then the TaskRunnerListener.errorResolved and PendingTaskStatusListener.errorResolved will not be called.

Note: The task runner will attempt to run your task after it has been resolved immediately. If the task belongs to a group, the task runner will attempt to run all the tasks in the group.

Parameters

taskId - The taskId of a PendingTask previously recorded an error for.

+

Exceptions

+

+IllegalArgumentException - If the PendingTask for the taskId provided does not exist.

Return
If PendingTask had a previously recorded error and it has been marked as resolved now.

See Also
diff --git a/docs/wendy/com.levibostian.wendy.service/-wendy/run-task.html b/docs/wendy/com.levibostian.wendy.service/-wendy/run-task.html index 8f10477..6fda3c3 100644 --- a/docs/wendy/com.levibostian.wendy.service/-wendy/run-task.html +++ b/docs/wendy/com.levibostian.wendy.service/-wendy/run-task.html @@ -13,7 +13,12 @@

runTask

Use this function along with manually run tasks to have Wendy run it for you. If it is successful, Wendy will take care of deleting it for you.

Parameters

-taskId - The PendingTask.taskId of PendingTask you wish to run. If there is not a PendingTask with this ID, the task runner simply ignores your request and moves on.

+taskId - The PendingTask.taskId of PendingTask you wish to run.

+

Exceptions

+

+IllegalArgumentException - If the PendingTask for the taskId provided does not exist.

+

+RuntimeException - If the PendingTask returns false for isTaskAbleToManuallyRun.

See Also

WendyConfig.addTaskStatusListenerForTask

diff --git a/docs/wendy/com.levibostian.wendy.service/-wendy/run-tasks.html b/docs/wendy/com.levibostian.wendy.service/-wendy/run-tasks.html index 2566b8a..befebb5 100644 --- a/docs/wendy/com.levibostian.wendy.service/-wendy/run-tasks.html +++ b/docs/wendy/com.levibostian.wendy.service/-wendy/run-tasks.html @@ -15,5 +15,8 @@

runTasks

Parameters

groupId - Limit running of the tasks to only tasks of this specific group id.

+

Exceptions

+

+RuntimeException - when in WendyConfig.strict mode and you say that your PendingTask was PendingTaskResult.SUCCESSFUL when you have an unresolved error recorded for that PendingTask.

diff --git a/docs/wendy/com.levibostian.wendy.types/-reason-pending-task-skipped/-n-o-t_-r-e-a-d-y_-t-o_-r-u-n/index.html b/docs/wendy/com.levibostian.wendy.types/-reason-pending-task-skipped/-n-o-t_-r-e-a-d-y_-t-o_-r-u-n/index.html index 84322d0..fabb863 100644 --- a/docs/wendy/com.levibostian.wendy.types/-reason-pending-task-skipped/-n-o-t_-r-e-a-d-y_-t-o_-r-u-n/index.html +++ b/docs/wendy/com.levibostian.wendy.types/-reason-pending-task-skipped/-n-o-t_-r-e-a-d-y_-t-o_-r-u-n/index.html @@ -12,7 +12,7 @@

NOT_READY_TO_RUN

NOT_READY_TO_RUN

The PendingTask of the app said that it was not ready to run.

See Also
-

PendingTask.canRunTask

+

PendingTask.isReadyToRun

Functions

diff --git a/docs/wendy/com.levibostian.wendy/-wendy-config/strict.html b/docs/wendy/com.levibostian.wendy/-wendy-config/strict.html index 613e612..97a8eb7 100644 --- a/docs/wendy/com.levibostian.wendy/-wendy-config/strict.html +++ b/docs/wendy/com.levibostian.wendy/-wendy-config/strict.html @@ -11,6 +11,8 @@

strict

var strict: Boolean

Sets Wendy to strict mode or not. Strict mode helps while developing your app to find and fix potential issues while working with Wendy.

+

Strict mode is only used in scenarios that a warning is not critical to the success of your app. How success if defined here is: (1) Your user does not get confused when they perform an action in your app and the request is simply ignored resulting in them being confused and (2) your app crashing only when you have hit a major issue that you really should fix (wendy cannot work without you fixing these crashes).

+

Wendy does still throw exceptions. Strict mode does not silence all exceptions. Strict simply gives you the option to silence warnings when it's really not a big deal that your code works in a certain way. It's assumed you know what you are doing.

When strict is true, warnings throw errors instead of logging the warning to the console. When strict is false, warnings get logged to the console and not crash your app instead.

Default: true

diff --git a/docs/wendy/index-outline.html b/docs/wendy/index-outline.html index cf07997..cd14f11 100644 --- a/docs/wendy/index-outline.html +++ b/docs/wendy/index-outline.html @@ -33,12 +33,12 @@ PendingTask(manuallyRun: Boolean, dataId: String?, groupId: String?, tag: String)
-open fun canRunTask(): Boolean
open var createdAt: Long
open var dataId: String?
fun equals(other: Any?): Boolean
open var groupId: String?
fun hashCode(): Int
+open fun isReadyToRun(): Boolean
open var manuallyRun: Boolean
@WorkerThread abstract fun runTask(): PendingTaskResult
open var tag: String
@@ -212,6 +212,7 @@ fun getAllTasks(): List<PendingTask>
fun getLatestError(taskId: Long): PendingTaskError?
@JvmStatic fun init(context: Context, tasksFactory: PendingTasksFactory): Wendy
+fun isTaskAbleToManuallyRun(taskId: Long): Boolean
fun recordError(taskId: Long, humanReadableErrorMessage: String?, errorId: String?): Unit
fun resolveError(taskId: Long): Boolean
fun runTask(taskId: Long): Unit
@@ -315,8 +316,10 @@ fun PendingTask.addTaskStatusListenerForTask(listener: PendingTaskStatusListener): Unit
+fun PendingTask.doesErrorExist(): Boolean
fun PendingTask.getLatestError(): PendingTaskError?
fun PendingTask.hasBeenAddedToWendy(): Boolean
+fun PendingTask.isAbleToManuallyRun(): Boolean
fun PendingTask.recordError(humanReadableErrorMessage: String?, errorId: String?): PendingTaskResult
fun PendingTaskError.resolveError(): Boolean
fun PendingTask.resolveError(): Unit
@@ -390,12 +393,12 @@ PendingTask(manuallyRun: Boolean, dataId: String?, groupId: String?, tag: String)
-open fun canRunTask(): Boolean
open var createdAt: Long
open var dataId: String?
fun equals(other: Any?): Boolean
open var groupId: String?
fun hashCode(): Int
+open fun isReadyToRun(): Boolean
open var manuallyRun: Boolean
@WorkerThread abstract fun runTask(): PendingTaskResult
open var tag: String
@@ -433,6 +436,7 @@ fun getAllTasks(): List<PendingTask>
fun getLatestError(taskId: Long): PendingTaskError?
@JvmStatic fun init(context: Context, tasksFactory: PendingTasksFactory): Wendy
+fun isTaskAbleToManuallyRun(taskId: Long): Boolean
fun recordError(taskId: Long, humanReadableErrorMessage: String?, errorId: String?): Unit
fun resolveError(taskId: Long): Boolean
fun runTask(taskId: Long): Unit