feat: query cancellation via `CancellationToken` on `SessionContext`
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 5/5
- Tempo estimado
- Mais de uma semana
- Facilidade para iniciantes
- 45/100
- Tipo de issue
- Funcionalidade
- Clareza
- Razoavelmente clara
- Status de atividade
- Pouca atividade
- Domínio
- api, backend-api-design
Direção de pesquisa
Comece pelos pontos de bloqueio de JNI em native/src/lib.rs e inspecione os pontos de entrada Java de SessionContext, DataFrame e dos resource handles. Compare o ciclo de vida de token proposto e as sobrecargas de collect/executeStream com as referências em cancellation.rs e query_tracker.rs. Considera-se concluído quando as APIs listadas oferecem suporte a cancelamento e limpeza sem alterar os métodos existentes sem token, com o cancelamento observável durante a coleta e o streaming.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Is your feature request related to a problem or challenge?
A long-running DataFrame.collect(allocator) or DataFrame.executeStream(allocator) call blocks the calling Java thread for the entire duration of the query. Thread.interrupt() does nothing — the JNI thread is parked inside runtime().block_on(...) (native/src/lib.rs), and the interrupt flag is ignored by the Tokio runtime. There is no way to abort an in-flight query, free its native resources early, or unblock the calling thread short of waiting for the query to finish.
For any embedder running multi-tenant workloads — request timeouts, user-cancel actions, node shutdown, leader-election handover — this is a hard operational gap. The OpenSearch analytics backend (OpenSearch/sandbox/plugins/analytics-backend-datafusion/rust/src/cancellation.rs and query_tracker.rs) carries a CancellationToken-based wrapper precisely because upstream offers nothing.
This is complementary to issue #40 (close()/JNI use-after-free race) but distinct: #40 is about safely tearing down a finished handle; this is about signalling an in-flight future to stop. Both eventually share the atomic-handle scaffolding from #40's option 2, so coordination is worthwhile, but the surface lands cleanly without #40 having to merge first.
Describe the solution you'd like
A token-based cancellation API on SessionContext, modeled on Spark 4.0's interruptTag shape (cancel lives on the session, not on the DataFrame). The token is a separate handle from the DataFrame so cancel can fire from a thread that does not hold the DataFrame.
v1 surface
try (SessionContext ctx = new SessionContext();
CancellationToken token = ctx.newCancellationToken();
DataFrame df = ctx.sql("SELECT ... FROM big_table")) {
Future<ArrowReader> fut = pool.submit(() -> df.collect(allocator, token));
// from another thread (timeout watcher, user-cancel handler, ...):
token.cancel();
// fut completes with CancellationException
}
New methods:
SessionContext.newCancellationToken()-- returns a freshCancellationTokenbound to this session.CancellationToken.cancel()-- fires the token; idempotent.CancellationToken.isCancelled()-- non-blocking check.CancellationToken.close()-- releases the native handle; the token isAutoCloseableso try-with-resources handles cleanup.DataFrame.collect(BufferAllocator, CancellationToken)-- overload that takes a token. The existing zero-tokencollect(BufferAllocator)is unchanged.DataFrame.executeStream(BufferAllocator, CancellationToken)-- same overload pattern. Token is held by the returnedArrowReaderfor its full lifetime; cancel mid-stream aborts the nextloadNextBatch().
Describe alternatives you've considered
No response
Additional context
Out of scope
- Tag form. Ship the token primitive first; tag is sugar that can land in a follow-up if a user actually asks for it.
- Sync-API breakage.
df.collect(allocator)keeps working unchanged; the new method isdf.collect(allocator, token)(overload). - Per-operator cancel granularity. Today the cancel point is each
block_onsite; sub-operator cancellation is upstream-DataFusion territory.
- Linguagem predominante
- Java
- Estrelas
- 32
- Forks
- 12
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de apache/datafusion-java
-
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 35/100
apache/datafusion-java#116 ·
-
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 25/100
apache/datafusion-java#112 ·
-
enhancement
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 42/100
apache/datafusion-java#96 ·
-
enhancement
Dificuldade 5/5 Mais de uma semana Facilidade para iniciantes 38/100
apache/datafusion-java#95 ·
-
Create first release Abertaenhancement
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 35/100
apache/datafusion-java#86 · 3 comentários ·
Todas as issues de apache/datafusion-java
Issues semelhantes
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 65/100
-
bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
elastic/gradle-plugins#157 ·
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
cryptomator/hub#497 ·
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
johanhaleby/occurrent#1120 ·