forked from alexjustesen/speedtest-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSpeedtestCallbackController.php
More file actions
134 lines (107 loc) · 3.97 KB
/
SpeedtestCallbackController.php
File metadata and controls
134 lines (107 loc) · 3.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<?php
namespace App\Http\Controllers\Api\V1;
use App\Enums\ResultStatus;
use App\Events\SpeedtestCompleted;
use App\Events\SpeedtestFailed;
use App\Events\SpeedtestRunning;
use App\Http\Controllers\Controller;
use App\Jobs\Ookla\BenchmarkSpeedtestJob;
use App\Models\Result;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Log;
class SpeedtestCallbackController extends Controller
{
/**
* Handle callback from Rust speedtest service.
*/
public function __invoke(Request $request): JsonResponse
{
Log::debug('received speedtest callback', [
'test_id' => $request->input('test_id'),
'status' => $request->input('status'),
]);
$resultId = $request->input('metadata.result_id');
if (! $resultId) {
Log::warning('callback missing result_id in metadata');
return response()->json(['error' => 'missing result_id'], 400);
}
$result = Result::find($resultId);
if (! $result) {
Log::warning('callback for unknown result', ['result_id' => $resultId]);
return response()->json(['error' => 'result not found'], 404);
}
$status = $request->input('status');
if ($status === 'failed') {
return $this->handleFailed($result, $request);
}
if ($status === 'completed') {
return $this->handleCompleted($result, $request);
}
// Running status update
if ($status === 'running') {
$result->update(['status' => ResultStatus::Running]);
SpeedtestRunning::dispatch($result);
return response()->json(['status' => 'acknowledged']);
}
return response()->json(['status' => 'ignored']);
}
/**
* Handle completed speedtest callback.
*/
protected function handleCompleted(Result $result, Request $request): JsonResponse
{
Log::info('speedtest completed via rust service', [
'result_id' => $result->id,
'test_id' => $request->input('test_id'),
]);
// Extract data from Rust service response
$rawOutput = $request->input('raw_output', []);
// Update result with speedtest data
$result->update([
'ping' => $request->input('ping'),
'download' => $this->mbpsToBytes($request->input('download')),
'upload' => $this->mbpsToBytes($request->input('upload')),
'download_bytes' => Arr::get($rawOutput, 'download.bytes'),
'upload_bytes' => Arr::get($rawOutput, 'upload.bytes'),
'data' => $rawOutput,
'status' => ResultStatus::Benchmarking,
]);
// Dispatch benchmark job
BenchmarkSpeedtestJob::dispatch($result);
// Complete the speedtest
$result->update(['status' => ResultStatus::Completed]);
SpeedtestCompleted::dispatch($result);
return response()->json(['status' => 'processed']);
}
/**
* Handle failed speedtest callback.
*/
protected function handleFailed(Result $result, Request $request): JsonResponse
{
Log::error('speedtest failed via rust service', [
'result_id' => $result->id,
'error' => $request->input('error'),
]);
$result->update([
'data->type' => 'log',
'data->level' => 'error',
'data->message' => $request->input('error', 'Unknown error from Rust service'),
'status' => ResultStatus::Failed,
]);
SpeedtestFailed::dispatch($result);
return response()->json(['status' => 'processed']);
}
/**
* Convert Mbps to bytes per second (Ookla format).
*/
protected function mbpsToBytes(?float $mbps): ?int
{
if ($mbps === null) {
return null;
}
// Convert Mbps to bytes/s (Ookla stores bandwidth in bytes/s)
return (int) (($mbps * 1_000_000) / 8);
}
}