Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
2 changes: 1 addition & 1 deletion server/src/Http/Filter/ContactFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public function phone(?string $phone)
public function address(?string $address)
{
$this->builder->whereHas(
'addresses',
'place',
function ($query) use ($address) {
$query->search($address);
}
Expand Down
13 changes: 11 additions & 2 deletions server/src/Http/Resources/v1/Index/Order.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,12 @@ public function toArray($request): array

// Latest status only, not full array
'latest_status' => $this->whenLoaded('trackingStatuses', function () {
$latest = $this->trackingStatuses->first();
$latest = $this->latestTrackingStatus();

return $latest ? $latest->status : 'created';
}),
'latest_status_code' => $this->whenLoaded('trackingStatuses', function () {
$latest = $this->trackingStatuses->first();
$latest = $this->latestTrackingStatus();

return $latest ? $latest->code : null;
}),
Expand Down Expand Up @@ -127,4 +127,13 @@ public function toArray($request): array
],
];
}

/**
* The newest loaded tracking status. The relation has no order, so the
* statuses are sorted here, newest insert first within the same second.
*/
protected function latestTrackingStatus(): mixed
{
return $this->trackingStatuses->sortBy([['created_at', 'desc'], ['id', 'desc']])->first();
}
}
3 changes: 2 additions & 1 deletion server/src/Listeners/HandleUserRemovedFromCompany.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ public function handle(UserRemovedFromCompany $event)

protected function deleteDriversForCompanyUser(string $companyUuid, string $userUuid): void
{
$this->driverQueryForCompanyUser($companyUuid, $userUuid)->delete();
// Delete each driver through the model so DriverObserver cleans up after it
$this->driverQueryForCompanyUser($companyUuid, $userUuid)->get()->each->delete();
}

protected function driverQueryForCompanyUser(string $companyUuid, string $userUuid): mixed
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
12 changes: 12 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
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
19 changes: 17 additions & 2 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 @@ -670,8 +681,12 @@ public function unassignCurrentJob(): bool
*/
public function assignVehicle(Vehicle $vehicle): self
{
// Unassign vehicle from other drivers
static::where('vehicle_uuid', $vehicle->uuid)->update(['vehicle_uuid' => null]);
// Unassign vehicle from other drivers. This driver is skipped: when it already holds the
// vehicle the save below isn't dirty, so it would not write the vehicle back
static::where('vehicle_uuid', $vehicle->uuid)
->when($this->uuid, fn ($query) => $query->where('uuid', '!=', $this->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