Description
waitForTask has three usability gaps compared to the other official SDKs (JS, Python, Go, Rust, .NET):
-
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).
-
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:
- meilisearch-js:
TaskClient.waitForTask(...): Promise<Task>, returns the task as soon as its status leaves enqueued / processing
- meilisearch-python:
Client.wait_for_task(uid, timeout_in_ms=5000, interval_in_ms=50) -> Task
- meilisearch-go:
WaitForTask(taskUID int64, interval time.Duration) (*Task, error)
- meilisearch-rust:
TaskInfo::wait_for_completion(client, interval, timeout) -> Result<Task, Error>
- meilisearch-dotnet:
MeilisearchClient.WaitForTaskAsync(taskUid, timeoutMs, intervalMs, ...) -> Task<TaskResource>
- 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.
Description
waitForTaskhas three usability gaps compared to the other official SDKs (JS, Python, Go, Rust, .NET):Client.waitForTask(int)cannot override the timeout.Index.waitForTaskhas a(taskUid, timeoutInMs, intervalInMs)overload, butClientonly exposes the no-arg form, so anything waited throughClient(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).waitForTaskreturnsvoid. The caller cannot tell whether the tasksucceeded,failedor wascanceledwithout a secondgetTaskround trip. Every other official SDK returns the finished task object from its wait method:TaskClient.waitForTask(...): Promise<Task>, returns the task as soon as its status leavesenqueued/processingClient.wait_for_task(uid, timeout_in_ms=5000, interval_in_ms=50) -> TaskWaitForTask(taskUID int64, interval time.Duration) (*Task, error)TaskInfo::wait_for_completion(client, interval, timeout) -> Result<Task, Error>MeilisearchClient.WaitForTaskAsync(taskUid, timeoutMs, intervalMs, ...) -> Task<TaskResource>MeilisearchTimeoutExceptionis 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. AnInterruptedExceptionis also reported as a bare timeout.Basic example
What users currently have to write around the SDK (Kotlin):
What it should look like:
Proposal
Client.waitForTask(int uid, int timeoutInMs, int intervalInMs).waitForTaskoverloads onClient,IndexandTasksHandlerreturn theTaskin its final state.failed/canceled: none of the SDKs linked above do, and it keeps existing callers that wait on an intentionally failing task working.MeilisearchTimeoutExceptiona message with the task uid, the timeout and the last status.Related: #725 (canceled tasks hanging in the loop), #669 (
InterruptedExceptionhandling).Other
voidtoTaskis source compatible but not binary compatible for callers compiled against an older jar.