Skip to content

waitForTask: expose timeout on Client, return the finished Task, and give the timeout exception a message #991

Description

@hwhang0917

Description

waitForTask has three usability gaps compared to the other official SDKs (JS, Python, Go, Rust, .NET):

  1. Client.waitForTask(int) cannot override the timeout. Index.waitForTask has a (taskUid, timeoutInMs, intervalInMs) overload, but Client only exposes the no-arg form, so anything waited through Client (index creation/deletion, swaps, dumps, snapshots, task cancellation, dynamic search rules, ...) is stuck with the hard-coded 5000ms / 50ms. Python exposes both parameters on the client with the same defaults (wait_for_task), and .NET does too (WaitForTaskAsync).

  2. waitForTask returns void. The caller cannot tell whether the task succeeded, failed or was canceled without a second getTask round trip. Every other official SDK returns the finished task object from its wait method:

  1. The timeout exception has no message. MeilisearchTimeoutException is thrown with no arguments: no task uid, no timeout value and no last observed status, so logs from a timed-out wait carry no useful information. An InterruptedException is also reported as a bare timeout.

Basic example

What users currently have to write around the SDK (Kotlin):

private fun awaitTask(taskUid: Int) {
    val deadline = System.currentTimeMillis() + TASK_TIMEOUT_MS
    while (true) {
        val task = client.getTask(taskUid)
        when (task.status) {
            TaskStatus.SUCCEEDED -> return
            TaskStatus.FAILED, TaskStatus.CANCELED -> error("Meilisearch task $taskUid ${task.status}: ${task.error?.code} ${task.error?.message}")
            else -> {
                check(System.currentTimeMillis() < deadline) { "Meilisearch task $taskUid timed out after ${TASK_TIMEOUT_MS}ms (last status: ${task.status})" }
                Thread.sleep(TASK_POLL_INTERVAL_MS)
            }
        }
    }
}

What it should look like:

val task = client.waitForTask(taskUid, TASK_TIMEOUT_MS, TASK_POLL_INTERVAL_MS)
check(task.status == TaskStatus.SUCCEEDED) { "task $taskUid ${task.status}: ${task.error?.code} ${task.error?.message}" }

Proposal

  • Add Client.waitForTask(int uid, int timeoutInMs, int intervalInMs).
  • Make all waitForTask overloads on Client, Index and TasksHandler return the Task in its final state.
  • Do not throw on failed / canceled: none of the SDKs linked above do, and it keeps existing callers that wait on an intentionally failing task working.
  • Give MeilisearchTimeoutException a message with the task uid, the timeout and the last status.

Related: #725 (canceled tasks hanging in the loop), #669 (InterruptedException handling).

Other

void to Task is source compatible but not binary compatible for callers compiled against an older jar.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions