From 698c99b9242f28c324576d02ee02a78a411b1474 Mon Sep 17 00:00:00 2001 From: thatguy2137 Date: Thu, 29 Jan 2026 00:07:10 -0500 Subject: [PATCH 1/4] Added skipping for recently errored outbox items --- app/Console/Commands/RevokeApiToken.php | 2 +- .../Api/FormSubmissionOutboxController.php | 19 +++++++++-- .../Api/FormSubmissionsController.php | 1 + app/Http/Middleware/ApiTokenAuth.php | 2 +- app/Models/FormSubmissionOutbox.php | 7 ++++ ...ror_at_to_form_submission_outbox_table.php | 33 +++++++++++++++++++ 6 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 database/migrations/2026_01_27_000001_add_last_error_at_to_form_submission_outbox_table.php diff --git a/app/Console/Commands/RevokeApiToken.php b/app/Console/Commands/RevokeApiToken.php index 480b622..dbbb7dc 100644 --- a/app/Console/Commands/RevokeApiToken.php +++ b/app/Console/Commands/RevokeApiToken.php @@ -43,7 +43,7 @@ public function handle() return self::SUCCESS; } - $token->forceFill(['revoked_at' => now()])->save(); + $token->fill(['revoked_at' => now()])->save(); $this->info('API token revoked.'); diff --git a/app/Http/Controllers/Api/FormSubmissionOutboxController.php b/app/Http/Controllers/Api/FormSubmissionOutboxController.php index 3e2e119..ae8c4fe 100644 --- a/app/Http/Controllers/Api/FormSubmissionOutboxController.php +++ b/app/Http/Controllers/Api/FormSubmissionOutboxController.php @@ -10,7 +10,13 @@ class FormSubmissionOutboxController extends Controller { public function next() { + $cutoff = now()->subMinutes(5); + $outboxItem = FormSubmissionOutbox::whereNull('processed_at') + ->where(function ($query) use ($cutoff) { + $query->whereNull('last_error_at') + ->orWhere('last_error_at', '<=', $cutoff); + }) ->orderBy('created_at') ->first(); @@ -33,24 +39,31 @@ public function next() 'user_id' => $formSubmission->user_id, 'data' => json_decode($formSubmission->data, true), 'created_at' => optional($formSubmission->created_at)->toDateTimeString(), + 'last_error' => $outboxItem->last_error, + 'last_error_at' => optional($outboxItem->last_error_at)->toDateTimeString(), ]); } public function markProcessed(Request $request, FormSubmissionOutbox $formSubmissionOutbox) { $lastError = $request->input('last_error'); - $updates = ['last_error' => $lastError]; + $updates = []; if (! $lastError) { $updates['processed_at'] = now(); + } else { + $updates['processed_at'] = null; + $updates['last_error'] = $lastError; + $updates['last_error_at'] = now(); } - $formSubmissionOutbox->forceFill($updates)->save(); + $formSubmissionOutbox->fill($updates)->save(); return response()->json([ 'outbox_id' => $formSubmissionOutbox->id, 'processed_at' => optional($formSubmissionOutbox->processed_at)->toDateTimeString(), 'last_error' => $formSubmissionOutbox->last_error, + 'last_error_at' => optional($formSubmissionOutbox->last_error_at)->toDateTimeString(), ]); } @@ -71,6 +84,8 @@ public function show(FormSubmissionOutbox $formSubmissionOutbox) 'user_id' => $formSubmission->user_id, 'data' => json_decode($formSubmission->data, true), 'created_at' => optional($formSubmission->created_at)->toDateTimeString(), + 'last_error' => $formSubmissionOutbox->last_error, + 'last_error_at' => optional($formSubmissionOutbox->last_error_at)->toDateTimeString(), ]); } } diff --git a/app/Http/Controllers/Api/FormSubmissionsController.php b/app/Http/Controllers/Api/FormSubmissionsController.php index 3bd7848..dba8faa 100644 --- a/app/Http/Controllers/Api/FormSubmissionsController.php +++ b/app/Http/Controllers/Api/FormSubmissionsController.php @@ -12,6 +12,7 @@ public function show(Request $request, FormSubmission $formSubmission) { return response()->json([ 'form_id' => $formSubmission->form_id, + 'form_submission_id' => $formSubmission->id, 'form_name' => $formSubmission->form_name, 'user_id' => $formSubmission->user_id, 'data' => json_decode($formSubmission->data, true), diff --git a/app/Http/Middleware/ApiTokenAuth.php b/app/Http/Middleware/ApiTokenAuth.php index f35493b..2b8df0b 100644 --- a/app/Http/Middleware/ApiTokenAuth.php +++ b/app/Http/Middleware/ApiTokenAuth.php @@ -30,7 +30,7 @@ public function handle(Request $request, Closure $next) return response()->json(['message' => 'Invalid API token.'], 401); } - $apiToken->forceFill(['last_used_at' => now()])->save(); + $apiToken->fill(['last_used_at' => now()])->save(); $request->attributes->set('api_token', $apiToken); return $next($request); diff --git a/app/Models/FormSubmissionOutbox.php b/app/Models/FormSubmissionOutbox.php index 09c5e14..676a9e9 100644 --- a/app/Models/FormSubmissionOutbox.php +++ b/app/Models/FormSubmissionOutbox.php @@ -15,6 +15,13 @@ class FormSubmissionOutbox extends Model 'form_submission_id', 'processed_at', 'last_error', + 'last_error_at', + ]; + + protected $casts = [ + 'created_at' => 'datetime', + 'processed_at' => 'datetime', + 'last_error_at' => 'datetime', ]; /** diff --git a/database/migrations/2026_01_27_000001_add_last_error_at_to_form_submission_outbox_table.php b/database/migrations/2026_01_27_000001_add_last_error_at_to_form_submission_outbox_table.php new file mode 100644 index 0000000..a2844bd --- /dev/null +++ b/database/migrations/2026_01_27_000001_add_last_error_at_to_form_submission_outbox_table.php @@ -0,0 +1,33 @@ +timestamp('last_error_at')->nullable()->after('last_error'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('form_submission_outbox', function (Blueprint $table) { + $table->dropColumn('last_error_at'); + }); + } +}; From 75c0772d1ce6466c17d9f2e956522c7216b7e46f Mon Sep 17 00:00:00 2001 From: thatguy2137 Date: Thu, 29 Jan 2026 01:04:54 -0500 Subject: [PATCH 2/4] Adding list endpoints --- .../Api/FormSubmissionOutboxController.php | 18 ++++++++++++++++++ .../Api/FormSubmissionsController.php | 17 +++++++++++++++++ routes/api.php | 2 ++ 3 files changed, 37 insertions(+) diff --git a/app/Http/Controllers/Api/FormSubmissionOutboxController.php b/app/Http/Controllers/Api/FormSubmissionOutboxController.php index ae8c4fe..2c07e0e 100644 --- a/app/Http/Controllers/Api/FormSubmissionOutboxController.php +++ b/app/Http/Controllers/Api/FormSubmissionOutboxController.php @@ -8,6 +8,24 @@ class FormSubmissionOutboxController extends Controller { + + public function index(Request $request) + { + $perPage = (int) $request->query('per_page', 50); + $perPage = max(1, min($perPage, 200)); + return FormSubmissionOutbox::query() + ->select([ + 'id', + 'form_submission_id', + 'processed_at', + 'last_error', + 'last_error_at', + 'created_at', + ]) + ->orderBy('id') + ->paginate($perPage); + } + public function next() { $cutoff = now()->subMinutes(5); diff --git a/app/Http/Controllers/Api/FormSubmissionsController.php b/app/Http/Controllers/Api/FormSubmissionsController.php index dba8faa..18ae107 100644 --- a/app/Http/Controllers/Api/FormSubmissionsController.php +++ b/app/Http/Controllers/Api/FormSubmissionsController.php @@ -8,6 +8,23 @@ class FormSubmissionsController extends Controller { + + public function index(Request $request) + { + $perPage = (int) $request->query('per_page', 50); + $perPage = max(1, min($perPage, 200)); + return FormSubmission::query() + ->select([ + 'id', + 'form_id', + 'form_name', + 'user_id', + 'created_at', + ]) + ->orderBy('id') + ->paginate($perPage); + } + public function show(Request $request, FormSubmission $formSubmission) { return response()->json([ diff --git a/routes/api.php b/routes/api.php index 753b2fc..3dfda36 100644 --- a/routes/api.php +++ b/routes/api.php @@ -26,7 +26,9 @@ Route::middleware('api_token')->get('/token', [ApiTokenController::class, 'show']); Route::middleware('api_token')->get('/users', [UsersController::class, 'index']); Route::middleware('api_token')->get('/users/{user}', [UsersController::class, 'show']); +Route::middleware('api_token')->get('/form_submissions', [FormSubmissionsController::class, 'index']); Route::middleware('api_token')->get('/form_submissions/{form_submission}', [FormSubmissionsController::class, 'show']); +Route::middleware('api_token')->get('/form_submissions/outbox', [FormSubmissionOutboxController::class, 'index']); Route::middleware('api_token')->get('/form_submissions/outbox/next', [FormSubmissionOutboxController::class, 'next']); Route::middleware('api_token')->post('/form_submissions/outbox/{form_submission_outbox}', [FormSubmissionOutboxController::class, 'markProcessed']); Route::middleware('api_token')->get('/form_submissions/outbox/{form_submission_outbox}', [FormSubmissionOutboxController::class, 'show']); From 6015191dd9ef9b23d5a7afa62fdd017f0e6fc093 Mon Sep 17 00:00:00 2001 From: thatguy2137 Date: Fri, 30 Jan 2026 01:12:56 -0500 Subject: [PATCH 3/4] Fixing linting --- app/Http/Controllers/Api/FormSubmissionOutboxController.php | 1 - app/Http/Controllers/Api/FormSubmissionsController.php | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/Http/Controllers/Api/FormSubmissionOutboxController.php b/app/Http/Controllers/Api/FormSubmissionOutboxController.php index 2c07e0e..525ea24 100644 --- a/app/Http/Controllers/Api/FormSubmissionOutboxController.php +++ b/app/Http/Controllers/Api/FormSubmissionOutboxController.php @@ -8,7 +8,6 @@ class FormSubmissionOutboxController extends Controller { - public function index(Request $request) { $perPage = (int) $request->query('per_page', 50); diff --git a/app/Http/Controllers/Api/FormSubmissionsController.php b/app/Http/Controllers/Api/FormSubmissionsController.php index 18ae107..061fd8b 100644 --- a/app/Http/Controllers/Api/FormSubmissionsController.php +++ b/app/Http/Controllers/Api/FormSubmissionsController.php @@ -8,7 +8,6 @@ class FormSubmissionsController extends Controller { - public function index(Request $request) { $perPage = (int) $request->query('per_page', 50); @@ -24,7 +23,7 @@ public function index(Request $request) ->orderBy('id') ->paginate($perPage); } - + public function show(Request $request, FormSubmission $formSubmission) { return response()->json([ From 3c454a9ee8463235d85ca4ea20dc1e75025ffcc8 Mon Sep 17 00:00:00 2001 From: thatguy2137 Date: Fri, 30 Jan 2026 01:25:50 -0500 Subject: [PATCH 4/4] Fixing linting --- app/Http/Controllers/Api/FormSubmissionOutboxController.php | 1 + app/Http/Controllers/Api/FormSubmissionsController.php | 1 + 2 files changed, 2 insertions(+) diff --git a/app/Http/Controllers/Api/FormSubmissionOutboxController.php b/app/Http/Controllers/Api/FormSubmissionOutboxController.php index 525ea24..7f781ed 100644 --- a/app/Http/Controllers/Api/FormSubmissionOutboxController.php +++ b/app/Http/Controllers/Api/FormSubmissionOutboxController.php @@ -12,6 +12,7 @@ public function index(Request $request) { $perPage = (int) $request->query('per_page', 50); $perPage = max(1, min($perPage, 200)); + return FormSubmissionOutbox::query() ->select([ 'id', diff --git a/app/Http/Controllers/Api/FormSubmissionsController.php b/app/Http/Controllers/Api/FormSubmissionsController.php index 061fd8b..272abcc 100644 --- a/app/Http/Controllers/Api/FormSubmissionsController.php +++ b/app/Http/Controllers/Api/FormSubmissionsController.php @@ -12,6 +12,7 @@ public function index(Request $request) { $perPage = (int) $request->query('per_page', 50); $perPage = max(1, min($perPage, 200)); + return FormSubmission::query() ->select([ 'id',