Skip to content
1 change: 1 addition & 0 deletions server/src/Console/Commands/ProcessOperationalAlerts.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ protected function notifyOnce(Order $order, string $key, string $notificationCla
'context' => $context,
]);
$order->saveQuietly();
$order->invalidateApiCache();
}

return true;
Expand Down
9 changes: 9 additions & 0 deletions server/src/Http/Controllers/Api/v1/DriverController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
use Fleetbase\FleetOps\Models\Order;
use Fleetbase\FleetOps\Models\Vehicle;
use Fleetbase\FleetOps\Models\Vendor;
use Fleetbase\FleetOps\Support\ApiCacheThrottle;
use Fleetbase\FleetOps\Support\GeofenceIntersectionService;
use Fleetbase\FleetOps\Support\OSRM;
use Fleetbase\FleetOps\Support\ProfileAccountManager;
Expand Down Expand Up @@ -374,6 +375,12 @@ public function track(string $id, Request $request)
}
}

// Location writes are quiet and frequent: invalidate cached lists at most once a window
ApiCacheThrottle::invalidate($driver, $driver->company_uuid);
if ($vehicle) {
ApiCacheThrottle::invalidate($vehicle, $vehicle->company_uuid);
}

broadcast(new DriverLocationChanged($driver));
app(TrackingPublisher::class)->driverMoved($driver);

Expand Down Expand Up @@ -433,11 +440,13 @@ public function toggleOnline(string $id, Request $request)

// Perform a single update call
$driver->updateQuietly(['online' => $onlineValue]);
$driver->invalidateApiCache();

// Update vehicle online too
$driver->loadMissing('vehicle');
if ($vehicle = $driver->vehicle) {
$vehicle->updateQuietly(['online' => $onlineValue]);
$vehicle->invalidateApiCache();
}

// Return the updated resource
Expand Down
14 changes: 10 additions & 4 deletions server/src/Http/Controllers/Api/v1/FleetController.php
Original file line number Diff line number Diff line change
Expand Up @@ -434,10 +434,13 @@ protected function assignMembership(string $pivotClass, array $attributes): void

protected function removeVehicleFromFleet(Fleet $fleet, Vehicle $vehicle): void
{
FleetVehicle::where([
// Deleted without model events; fleet_vehicles rows carry no company
if (FleetVehicle::where([
'fleet_uuid' => $fleet->uuid,
'vehicle_uuid' => $vehicle->uuid,
])->delete();
])->delete()) {
FleetVehicle::invalidateApiCacheManually();
}
}

protected function assignDriverToFleet(Fleet $fleet, Driver $driver): void
Expand All @@ -450,10 +453,13 @@ protected function assignDriverToFleet(Fleet $fleet, Driver $driver): void

protected function removeDriverFromFleet(Fleet $fleet, Driver $driver): void
{
FleetDriver::where([
// Deleted without model events; fleet_drivers rows carry no company
if (FleetDriver::where([
'fleet_uuid' => $fleet->uuid,
'driver_uuid' => $driver->uuid,
])->delete();
])->delete()) {
FleetDriver::invalidateApiCacheManually();
}
}

protected function vehicleMembershipPayload(Fleet $fleet, Vehicle $vehicle, bool $assigned): array
Expand Down
3 changes: 3 additions & 0 deletions server/src/Http/Controllers/Api/v1/VehicleController.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use Fleetbase\FleetOps\Models\Vehicle;
use Fleetbase\FleetOps\Models\Vendor;
use Fleetbase\FleetOps\Models\Warranty;
use Fleetbase\FleetOps\Support\ApiCacheThrottle;
use Fleetbase\FleetOps\Support\GeofenceIntersectionService;
use Fleetbase\FleetOps\Support\TrackingPublisher;
use Fleetbase\FleetOps\Support\Utils;
Expand Down Expand Up @@ -297,6 +298,8 @@ public function track(string $id, Request $request)

$vehicle->updateQuietly($positionData);
$vehicle->createPosition($positionData);
// Location writes are quiet and frequent: invalidate cached lists at most once a window
ApiCacheThrottle::invalidate($vehicle, $vehicle->company_uuid);

broadcast(new VehicleLocationChanged($vehicle));
app(TrackingPublisher::class)->vehicleMoved($vehicle);
Expand Down
3 changes: 3 additions & 0 deletions server/src/Http/Controllers/Internal/v1/ContactController.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Fleetbase\Http\Requests\ExportRequest;
use Fleetbase\Http\Requests\ImportRequest;
use Fleetbase\Models\User;
use Fleetbase\Support\ApiModelCache;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
Expand Down Expand Up @@ -266,6 +267,7 @@ protected function migrateContactCustomerContextToVendor(Contact $contact, Vendo
protected function bulkUpdateCustomerContext(string $modelClass, array $filter, array $replacement): void
{
$modelClass::where($filter)->update($replacement);
ApiModelCache::invalidateModelCache(new $modelClass(), session('company'));
}

protected function customerPortalIssuesForContact(Contact $contact)
Expand Down Expand Up @@ -350,6 +352,7 @@ protected function sendCustomerCredentialsMail(User $user, string $password, Con
protected function saveContactMetaQuietly(Contact $contact, array $meta): void
{
$contact->forceFill(['meta' => $meta])->saveQuietly();
$contact->invalidateApiCache();
}

protected function isCustomerPortalInstalled(): bool
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,7 @@ protected function clearDriverAssignmentsForOrders($orders): void
'driver_assigned_uuid' => null,
'updated_at' => now(),
]);
Order::invalidateApiCacheManually(session('company'));
}

protected function freshOrders($orders, array $with)
Expand Down
18 changes: 16 additions & 2 deletions server/src/Http/Controllers/Internal/v1/FleetController.php
Original file line number Diff line number Diff line change
Expand Up @@ -250,10 +250,17 @@ protected static function createFleetDriverAssignment(string $fleetUuid, string

protected static function deleteFleetDriverAssignment(string $fleetUuid, string $driverUuid): mixed
{
return FleetDriver::where([
$deleted = FleetDriver::where([
'fleet_uuid' => $fleetUuid,
'driver_uuid' => $driverUuid,
])->delete();

// Deleted without model events; fleet_drivers rows carry no company
if ($deleted) {
FleetDriver::invalidateApiCacheManually();
}

return $deleted;
}

protected static function fleetVehicleAssignmentExists(string $fleetUuid, string $vehicleUuid): bool
Expand All @@ -274,10 +281,17 @@ protected static function createFleetVehicleAssignment(string $fleetUuid, string

protected static function deleteFleetVehicleAssignment(string $fleetUuid, string $vehicleUuid): mixed
{
return FleetVehicle::where([
$deleted = FleetVehicle::where([
'fleet_uuid' => $fleetUuid,
'vehicle_uuid' => $vehicleUuid,
])->delete();

// Deleted without model events; fleet_vehicles rows carry no company
if ($deleted) {
FleetVehicle::invalidateApiCacheManually();
}

return $deleted;
}

protected static function invalidateOperationsMonitor(): void
Expand Down
2 changes: 2 additions & 0 deletions server/src/Http/Controllers/Internal/v1/IssueController.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public function afterSave(Request $request, Issue $issue)
if ($assignee && $assignee->type === 'customer') {
$issue->assigned_to_uuid = null;
$issue->saveQuietly();
$issue->invalidateApiCache();
}
}

Expand All @@ -58,6 +59,7 @@ public function afterSave(Request $request, Issue $issue)
if ($order) {
$issue->order_uuid = $order->uuid;
$issue->saveQuietly();
$issue->invalidateApiCache();
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Fleetbase\FleetOps\Models\Place;
use Fleetbase\FleetOps\Models\Vehicle;
use Fleetbase\FleetOps\Models\Vendor;
use Fleetbase\FleetOps\Models\Waypoint;
use Fleetbase\FleetOps\Orchestration\Contracts\OrchestrationEngineInterface;
use Fleetbase\FleetOps\Orchestration\Engines\DriverAssignmentEngine;
use Fleetbase\FleetOps\Orchestration\Engines\RouteSequencingEngine;
Expand Down Expand Up @@ -489,9 +490,10 @@ public function commit(Request $request): JsonResponse
return response()->json(['error' => 'No assignments provided.'], 422);
}

$committed = [];
$failed = [];
$manifests = [];
$committed = [];
$failed = [];
$manifests = [];
$resequenced = false;

$this->beginOrchestrationTransaction();
try {
Expand Down Expand Up @@ -576,6 +578,7 @@ public function commit(Request $request): JsonResponse
if (!empty($assignment['waypoint_sequence']) && $order->payload) {
foreach ($assignment['waypoint_sequence'] as $seq => $waypointId) {
$this->updateWaypointSequence($order->payload_uuid, $waypointId, $seq);
$resequenced = true;
}
}

Expand All @@ -597,6 +600,11 @@ public function commit(Request $request): JsonResponse
return response()->json(['error' => 'Commit failed: ' . $e->getMessage()], 500);
}

// Waypoint sequences are written without model events
if ($resequenced) {
Waypoint::invalidateApiCacheManually($companyUuid);
}

return response()->json([
'committed' => $committed,
'failed' => $failed,
Expand Down
2 changes: 2 additions & 0 deletions server/src/Http/Controllers/Internal/v1/OrderController.php
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ protected function assignDriverToOrders($orderUuids, Driver $driver): void
'driver_assigned_uuid' => $driver->uuid,
'updated_at' => now(),
]);
Order::invalidateApiCacheManually(session('company'));
}

protected function dispatchBulkAssignedDriverNotification(array $orderUuids, Driver $driver): void
Expand Down Expand Up @@ -2005,6 +2006,7 @@ public function scheduleOrder(Request $request)
}

$order->saveQuietly();
$order->invalidateApiCache();

return response()->json([
'status' => 'OK',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ public function detach(string $id)
'updated_by_uuid' => session('user'),
'updated_at' => now(),
]));
AssetConnection::invalidateApiCacheManually(session('company'));

return response()->json([
'status' => 'ok',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ public function unassignOrders(Request $request, string $id): JsonResponse
'updated_at' => now(),
]);
});
Order::invalidateApiCacheManually(session('company'));

return response()->json([
'status' => 'ok',
Expand Down
1 change: 1 addition & 0 deletions server/src/Http/Controllers/Public/TrackingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ protected function saveInstructions(Order $order, TrackingScope $scope, string $
$instructions[sha1($scope->key())] = $text;
$order->setMeta('recipient_instructions', $instructions);
$order->saveQuietly();
$order->invalidateApiCache();
}

protected function dataUrl(string $raw): string
Expand Down
3 changes: 3 additions & 0 deletions server/src/Models/AssetConnection.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Fleetbase\Casts\Json;
use Fleetbase\Casts\PolymorphicType;
use Fleetbase\Models\Model;
use Fleetbase\Traits\HasApiModelCache;
use Fleetbase\Traits\HasPublicId;
use Fleetbase\Traits\HasUuid;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
Expand All @@ -14,6 +15,8 @@
class AssetConnection extends Model
{
use HasUuid;
// Writes bump the asset_connections API cache version, which cached vehicle lists filter on.
use HasApiModelCache;
use HasPublicId;
use SoftDeletes;

Expand Down
1 change: 1 addition & 0 deletions server/src/Models/Contact.php
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ public function repairCustomerTypeInvariant(bool $quiet = false): ?User
]);
$user->forceFill(['type' => 'customer'])->saveQuietly();
$this->forceFill(['user_uuid' => $user->uuid])->saveQuietly();
$this->invalidateApiCache();
} else {
$user = $this->createUser();
}
Expand Down
28 changes: 28 additions & 0 deletions server/src/Models/Device.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,18 @@ class Device extends Model
*/
protected $table = 'devices';

/**
* Relation paths and tables the cached device lists embed (fleetbase/core-api#301).
*
* Lists load telematic, warranty and attachable and count sensors.
* attachable is a morphTo to a vehicle or trailer, so its tables are named.
* photo (public list) is left out: files is written by every upload, and a
* new photo is set by writing the device's own photo_uuid.
*
* @var string[]
*/
protected $apiCacheDependencies = ['telematic', 'warranty', 'sensors', 'vehicles', 'assets'];

/**
* The type of public Id to generate.
*
Expand Down Expand Up @@ -453,6 +465,10 @@ public function attachTo(Model $attachable): bool
});

if ($updated) {
// Cached vehicle and trailer lists filter on attached devices without depending on
// the device table, which telemetry writes on every ping
static::invalidateAttachableApiCache($attachable, $this->company_uuid);

activity('device_attached')
->performedOn($this)
->withProperties([
Expand All @@ -466,6 +482,14 @@ public function attachTo(Model $attachable): bool
return $updated;
}

/**
* Invalidate the cached lists of the attached model's table (vehicles or trailers).
*/
protected static function invalidateAttachableApiCache(\Illuminate\Database\Eloquent\Model $attachable, ?string $companyUuid): void
{
\Fleetbase\Support\ApiModelCache::invalidateModelCache($attachable, $companyUuid);
}

/**
* Detach the device from its current attachment.
*/
Expand All @@ -483,6 +507,10 @@ public function detach(): bool
return $this->update(['attachable_type' => null, 'attachable_uuid' => null]);
});

if ($updated && $oldAttachableType && is_a($oldAttachableType, \Illuminate\Database\Eloquent\Model::class, true)) {
static::invalidateAttachableApiCache(new $oldAttachableType(), $this->company_uuid);
}

if ($updated) {
activity('device_detached')
->performedOn($this)
Expand Down
7 changes: 7 additions & 0 deletions server/src/Models/DeviceEvent.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,13 @@ class DeviceEvent extends Model
*/
protected $table = 'device_events';

/**
* Relation paths the cached device event lists embed (fleetbase/core-api#301).
*
* @var string[]
*/
protected $apiCacheDependencies = ['device', 'device.telematic'];

/**
* The type of public Id to generate.
*
Expand Down
12 changes: 12 additions & 0 deletions server/src/Models/Driver.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,17 @@ class Driver extends Model
*/
protected $with = [];

/**
* Relation paths the cached driver lists depend on (fleetbase/core-api#301).
*
* Lists eager load nothing, but which drivers they hold depends on the
* user (existence, name, email and phone search), the vehicle (vehicle
* search) and the fleets (fleet filter, through fleet_drivers).
*
* @var string[]
*/
protected $apiCacheDependencies = ['user', 'vehicle', 'fleets'];

/**
* Dynamic attributes that are appended to object.
*
Expand Down Expand Up @@ -672,6 +683,7 @@ public function assignVehicle(Vehicle $vehicle): self
{
// Unassign vehicle from other drivers
static::where('vehicle_uuid', $vehicle->uuid)->update(['vehicle_uuid' => null]);
static::invalidateApiCacheManually($vehicle->company_uuid ?? $this->company_uuid);

// Set this vehicle to the driver instance
$this->setVehicle($vehicle);
Expand Down
Loading
Loading