Josh Salway 8f341895a9 [4.x] fix(actions): batch cancel, failed() handler, explicit retry defaults (#19754)
* fix(actions): add batch-cancel early-return and failed() handler to ExportCsv and ImportCsv

Two pure additions on both row-processor jobs. No existing property
is touched; `$maxExceptions = 5`, `retryUntil()`, `backoff()`,
`middleware()`, and `tags()` delegation all preserved.

- `if ($this->batch()?->cancelled()) { return; }` at the top of
  `handle()` so a batch cancelled via `Bus::findBatch($id)->cancel()`
  stops in-flight chunks on the next worker cycle instead of running
  every popped chunk to completion.
- `failed()` handler with scalar-only log context (`export_id` /
  `import_id`, `page`, `batch_id`, exception class, exception
  message). No secret leakage.

Tests:

- `{Export,Import}CsvBatchCancellationTest`: use
  `withFakeBatch(cancelledAt: ...)` + Mockery
  `shouldNotReceive('getAttribute')->with('user')` to prove the
  early-return fires.
- `{Export,Import}CsvFailedHandlerTest`: call
  `failed(new RuntimeException(...))` against `Log::shouldReceive('error')`
  to pin the structured log context shape.

* fix(actions): add failed() + explicit $tries/$maxExceptions to three standalone jobs

These three jobs have never had retry properties set. The implicit
design is "inherit the worker default," which varies by platform:
`queue:work` uses 1, `vapor:work` signature says 0 but runtime
overrides to `SQS_TRIES ?? 3`, Horizon supervisor configs vary.
Make the intent explicit per each job's idempotency and runtime
profile.

PrepareCsvExport (Batchable orchestrator, non-idempotent):
`$tries = 1` (retry would re-dispatch children via `batch()->add()`),
`$maxExceptions = 0`, batch-cancel early-return, `failed()` handler.
No `$timeout`: work scales with source-query size, keep worker-
inherited timeout rather than cap at 60s.

ExportCompletion (not Batchable, non-idempotent notifier):
`$tries = 1` (retry would double-notify), `$maxExceptions = 0`,
`failed()` handler. No `$timeout`: single `Notification::send()` or
`Notification::sendToDatabase()` call, sub-second runtime.

CreateXlsxFile (not Batchable, idempotent file converter):
`$tries = 3` (re-reads CSV chunks and overwrites same XLSX, so
transient failures recover), `$backoff = [30, 60, 300]` (avoids
0-second retry loop since `$tries > 1`), `$maxExceptions = 0`,
`failed()` handler. No `$timeout`: XLSX conversion runtime is
O(row count), large exports need worker-inherited timeout (Vapor
Lambda ceiling, Horizon supervisor) rather than 60s cap.

None of these three delegate `retryUntil()`, so `$tries` is the
active attempts bound. Public API unchanged.

* Remove tests (too brittle)

* Remove failed() hooks (too opinionated)

* cs

---------

Co-authored-by: Dan Harrin <git@danharrin.com>
2026-04-24 08:49:45 +01:00
2026-02-24 21:41:58 +00:00
2023-06-05 17:01:11 +02:00
2023-08-18 10:25:52 +02:00
wip
2024-02-27 22:02:36 +08:00
2025-01-24 08:26:51 +00:00
2026-04-20 13:25:22 +01:00
2025-03-20 11:01:45 +00:00
2024-07-21 11:04:29 +01:00
2022-07-15 09:24:26 +00:00
2025-08-12 09:53:53 +01:00
2023-08-07 09:55:28 +01:00
2025-01-23 12:51:54 +00:00
2026-02-24 21:45:58 +00:00
2025-03-02 11:05:32 +00:00
2025-03-20 11:01:45 +00:00

Banner

Tests passing Laravel v11+ Livewire v3 PHP 8.2+

filamentphp%2Ffilament | Trendshift

Build apps & admin panels fast, for your bright ideas.

With a solid Laravel foundation and a polished UI, you can focus on what makes your product unique. Filament gives you UI components that you won't outgrow — a cohesive set of well-considered building blocks that adapt as your application grows in complexity.

  • Tables — Browse and filter large datasets with powerful columns, actions, and bulk operations.
  • Forms — Build complex, reactive forms using a set of reusable, state-aware components.
  • Infolists — Render read-only record views with structured layouts and custom formatting.
  • Notifications — Trigger in-app feedback for actions, errors, and system events with minimal setup.
  • Dashboard widgets — Surface key metrics and trends using live, data-driven widgets tailored to each user.
  • Action modals — Handle confirmations and data entry with focused modal workflows tied to actions.

Get StartedLaunch DemoJoin Discord


Special thanks to Warp for sponsoring Filament through GitHub Sponsors:

Warp sponsorship

Warp, built for coding with multiple AI agents.


Contributing

Please see our contributing guide.

Need Help?

🐞 If you spot a bug, please submit a detailed issue, and wait for assistance.

🤔 If you have a question or feature request, please start a new discussion. We also have a Discord community. For quick help, ask questions in the appropriate channel.

🔐 If you discover a vulnerability, please review our security policy.

S
Description
A powerful open source UI framework for Laravel • Build and ship admin panels & apps fast with Livewire
Readme 693 MiB
Languages
PHP 89.2%
JavaScript 5.2%
Blade 3.6%
CSS 1.9%