fix handle retry button

This commit is contained in:
arifal
2025-03-25 15:54:02 +07:00
parent e7950e22f2
commit 091b1f305e
10 changed files with 234 additions and 42 deletions

View File

@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api;
use App\Enums\ImportDatasourceStatus; use App\Enums\ImportDatasourceStatus;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Jobs\RetrySyncronizeJob;
use App\Jobs\ScrapingDataJob; use App\Jobs\ScrapingDataJob;
use App\Jobs\SyncronizeSIMBG; use App\Jobs\SyncronizeSIMBG;
use App\Models\ImportDatasource; use App\Models\ImportDatasource;
@@ -37,35 +38,25 @@ class ScrapingController extends Controller
return $this->resSuccess(["message" => "Success execute scraping service on background, check status for more"]); return $this->resSuccess(["message" => "Success execute scraping service on background, check status for more"]);
} }
/** public function retry_syncjob(string $import_datasource_id){
* Store a newly created resource in storage. try{
*/
public function store(Request $request) $import_datasource = ImportDatasource::find($import_datasource_id);
{ if(!$import_datasource){
// return $this->resError("Invalid import datasource id", null, 404);
} }
/** dispatch(new RetrySyncronizeJob($import_datasource->id));
* Display the specified resource. return response()->json([
*/ "success" => true,
public function show(string $id) "message" => "Retrying scrape job on background, check status for more"
{ ]);
// }catch(\Exception $e){
return response()->json([
"success" => false,
"message" => "Failed to retry sync job",
"error" => $e->getMessage()
]);
} }
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
} }
} }

View File

@@ -29,6 +29,7 @@ class ImportDatasourceResource extends JsonResource
"finish_time" => $finishTime ? $finishTime->toDateTimeString() : null, "finish_time" => $finishTime ? $finishTime->toDateTimeString() : null,
"created_at" => $this->created_at->toDateTimeString(), "created_at" => $this->created_at->toDateTimeString(),
"updated_at" => $this->updated_at->toDateTimeString(), "updated_at" => $this->updated_at->toDateTimeString(),
"failed_uuid" => $this->failed_uuid
]; ];
} }
} }

View File

@@ -0,0 +1,76 @@
<?php
namespace App\Jobs;
use App\Enums\ImportDatasourceStatus;
use App\Models\BigdataResume;
use App\Models\ImportDatasource;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use App\Services\ServiceTabPbgTask;
use App\Services\ServiceGoogleSheet;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class RetrySyncronizeJob implements ShouldQueue
{
use Queueable, Dispatchable, InteractsWithQueue, SerializesModels;
private $import_datasource_id;
public function __construct(int $import_datasource_id)
{
$this->import_datasource_id = $import_datasource_id;
}
/**
* Execute the job.
*/
public function handle(): void
{
try{
$service_tab_pbg_task = app(ServiceTabPbgTask::class);
$service_google_sheet = app(ServiceGoogleSheet::class);
$failed_import = ImportDatasource::find($this->import_datasource_id);
$failed_import->update([
'message' => "Retrying from UUID: ". $failed_import->failed_uuid,
'status' => ImportDatasourceStatus::Processing->value,
'start_time' => now()
]);
$current_failed_uuid = null;
try{
$service_tab_pbg_task->run_service($failed_import->failed_uuid);
}catch(\Exception $e){
$current_failed_uuid = $service_tab_pbg_task->getFailedUUID();
throw $e;
}
$data_setting_result = $service_google_sheet->get_big_resume_data();
BigdataResume::generateResumeData($failed_import->id, "all", $data_setting_result);
BigdataResume::generateResumeData($failed_import->id, now()->year, $data_setting_result);
$failed_import->update([
'status' => ImportDatasourceStatus::Success->value,
'message' => "Retry completed successfully from UUID: ". $failed_import->failed_uuid,
'finish_time' => now(),
'failed_uuid' => null
]);
}catch(\Exception $e){
\Log::error("RetrySyncronizeJob Failed: ". $e->getMessage(), [
'exception' => $e,
]);
if(isset($failed_import)){
$failed_import->update([
'status' => ImportDatasourceStatus::Failed->value,
'message' => "Retry failed from UUID: ". $failed_import->failed_uuid,
'finish_time' => now(),
'failed_uuid' => $current_failed_uuid
]);
}
$this->fail($e);
}
}
}

View File

@@ -44,13 +44,21 @@ class ScrapingDataJob implements ShouldQueue
'message' => 'Initiating scraping...', 'message' => 'Initiating scraping...',
'response_body' => null, 'response_body' => null,
'status' => 'processing', 'status' => 'processing',
'start_time' => now() 'start_time' => now(),
'failed_uuid' => null
]); ]);
$failed_uuid = null;
// Run the scraping services // Run the scraping services
$service_google_sheet->run_service(); $service_google_sheet->run_service();
$service_pbg_task->run_service(); $service_pbg_task->run_service();
try{
$service_tab_pbg_task->run_service(); $service_tab_pbg_task->run_service();
}catch(\Exception $e){
$failed_uuid = $service_tab_pbg_task->getFailedUUID();
throw $e;
}
$data_setting_result = $service_google_sheet->get_big_resume_data(); $data_setting_result = $service_google_sheet->get_big_resume_data();
@@ -72,7 +80,8 @@ class ScrapingDataJob implements ShouldQueue
$import_datasource->update([ $import_datasource->update([
'status' => 'failed', 'status' => 'failed',
'response_body' => 'Error: ' . $e->getMessage(), 'response_body' => 'Error: ' . $e->getMessage(),
'finish_time' => now() 'finish_time' => now(),
'failed_uuid' => $failed_uuid,
]); ]);
} }

View File

@@ -158,8 +158,6 @@ class ServicePbgTask
]); ]);
} }
Log::info("Page {$currentPage} fetched & saved", ['records' => count($saved_data)]);
$currentPage++; $currentPage++;
} while ($currentPage <= $totalPage); } while ($currentPage <= $totalPage);

View File

@@ -19,6 +19,7 @@ class ServiceTabPbgTask
private $service_token; private $service_token;
private $user_token; private $user_token;
private $user_refresh_token; private $user_refresh_token;
protected $current_uuid = null;
public function __construct(Client $client, ServiceTokenSIMBG $service_token) public function __construct(Client $client, ServiceTokenSIMBG $service_token)
{ {
@@ -34,24 +35,41 @@ class ServiceTabPbgTask
$this->user_refresh_token = $auth_data['refresh']; $this->user_refresh_token = $auth_data['refresh'];
} }
public function run_service() public function run_service($retry_uuid = null)
{ {
try { try {
$pbg_tasks = PbgTask::all(); $pbg_tasks = PbgTask::orderBy('id')->get();
$start = false;
foreach ($pbg_tasks as $pbg_task) { foreach ($pbg_tasks as $pbg_task) {
if($retry_uuid){
if($pbg_task->uuid === $retry_uuid){
$start = true;
}
if(!$start){
continue;
}
}
try{
$this->current_uuid = $pbg_task->uuid;
$this->scraping_task_assignments($pbg_task->uuid); $this->scraping_task_assignments($pbg_task->uuid);
$this->scraping_task_retributions($pbg_task->uuid); $this->scraping_task_retributions($pbg_task->uuid);
$this->scraping_task_integrations($pbg_task->uuid); $this->scraping_task_integrations($pbg_task->uuid);
}catch(\Exception $e){
// Process task assignments here if needed Log::error("Failed on UUID: {$this->current_uuid}, Error: " . $e->getMessage());
Log::info("Successfully fetched for UUID: {$pbg_task->uuid}");
}
} catch (\Exception $e) {
Log::error("Failed to scrape task assignments: " . $e->getMessage());
throw $e; throw $e;
} }
} }
} catch (\Exception $e) {
Log::error("Failed to syncronize: " . $e->getMessage());
throw $e;
}
}
public function getFailedUUID(){
return $this->current_uuid;
}
private function scraping_task_assignments($uuid) private function scraping_task_assignments($uuid)
{ {

View File

@@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('import_datasources', function (Blueprint $table) {
$table->string('failed_uuid')->nullable()->after('status');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('import_datasources', function (Blueprint $table) {
$table->dropColumn('failed_uuid');
});
}
};

View File

@@ -27,6 +27,7 @@ class BigdataResume {
this.table = new Grid({ this.table = new Grid({
columns: [ columns: [
{ name: "ID" }, { name: "ID" },
{ name: "Year" },
{ name: "Jumlah Potensi" }, { name: "Jumlah Potensi" },
{ name: "Total Potensi" }, { name: "Total Potensi" },
{ name: "Jumlah Berkas Belum Terverifikasi" }, { name: "Jumlah Berkas Belum Terverifikasi" },
@@ -79,6 +80,7 @@ class BigdataResume {
then: (data) => { then: (data) => {
return data.data.map((item) => [ return data.data.map((item) => [
item.id, item.id,
item.year,
item.potention_count, item.potention_count,
addThousandSeparators(item.potention_sum), addThousandSeparators(item.potention_sum),
item.non_verified_count, item.non_verified_count,

View File

@@ -28,6 +28,19 @@ class SyncronizeTask {
"Duration", "Duration",
"Finished", "Finished",
"Created", "Created",
{
name: "Action",
formatter: (cell) => {
if (cell.status === "failed") {
return gridjs.html(`
<button data-id="${cell.id}" class="btn btn-sm btn-warning d-flex align-items-center gap-1 btn-retry">
<iconify-icon icon="mingcute:refresh-3-line" width="15" height="15"></iconify-icon>
<span>Retry</span>
</button>
`);
}
},
},
], ],
search: { search: {
server: { server: {
@@ -62,10 +75,20 @@ class SyncronizeTask {
item.duration, item.duration,
item.finish_time, item.finish_time,
item.created_at, item.created_at,
item,
]), ]),
total: (data) => data.meta.total, total: (data) => data.meta.total,
}, },
}).render(tableContainer); }).render(tableContainer);
tableContainer.addEventListener("click", (event) => {
let btn = event.target.closest(".btn-retry");
if (btn) {
const id = btn.getAttribute("data-id");
btn.disabled = true;
this.handleRetrySync(id, btn);
}
});
} }
handleSubmitSync() { handleSubmitSync() {
const button = document.getElementById("btn-sync-submit"); const button = document.getElementById("btn-sync-submit");
@@ -117,6 +140,48 @@ class SyncronizeTask {
}); });
} }
handleRetrySync(id, btn) {
const apiToken = document
.querySelector('meta[name="api-token"]')
.getAttribute("content");
fetch(`${GlobalConfig.apiHost}/api/retry-scraping/${id}`, {
method: "GET",
headers: {
Authorization: `Bearer ${apiToken}`,
"Content-Type": "application/json",
},
})
.then(async (response) => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then((data) => {
console.log("API Response:", data); // Debugging
// Show success message
const message =
data?.data?.message ||
data?.message ||
"Synchronization successful!";
this.toastMessage.innerText = message;
this.toast.show();
})
.catch((err) => {
console.error("Fetch error:", err);
// Show error message
this.toastMessage.innerText =
err.message ||
"Failed to synchronize, something went wrong!";
this.toast.show();
// Re-enable button on failure
btn.disabled = false;
});
}
handleSyncClick() { handleSyncClick() {
const button = document.getElementById("btn-sync-submit"); const button = document.getElementById("btn-sync-submit");
const spinner = document.getElementById("spinner"); const spinner = document.getElementById("spinner");

View File

@@ -72,7 +72,11 @@ Route::group(['middleware' => 'auth:sanctum'], function (){
}); });
// scraping // scraping
Route::apiResource('/scraping', ScrapingController::class); Route::controller(ScrapingController::class)->group(function (){
Route::get('/scraping','index')->name('scraping');
Route::get('/retry-scraping/{id}','retry_syncjob')->name('retry-scraping');
});
// Route::apiResource('/scraping', ScrapingController::class);
// reklame // reklame
Route::apiResource('advertisements', AdvertisementController::class); Route::apiResource('advertisements', AdvertisementController::class);