From 562e05cac4f374906b04c6c32da44d61ba2ffca0 Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Tue, 20 Jan 2026 07:44:44 -0800 Subject: [PATCH] Use queue for position cache --- .../traccar/session/cache/CacheManager.java | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/org/traccar/session/cache/CacheManager.java b/src/main/java/org/traccar/session/cache/CacheManager.java index 20886f901..9938966a2 100644 --- a/src/main/java/org/traccar/session/cache/CacheManager.java +++ b/src/main/java/org/traccar/session/cache/CacheManager.java @@ -1,5 +1,5 @@ /* - * Copyright 2022 - 2025 Anton Tananaev (anton@traccar.org) + * Copyright 2022 - 2026 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -44,10 +44,12 @@ import org.traccar.storage.query.Columns; import org.traccar.storage.query.Condition; import org.traccar.storage.query.Request; +import java.util.AbstractQueue; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -66,7 +68,7 @@ public class CacheManager implements BroadcastInterface { private final CacheGraph graph = new CacheGraph(); private volatile Server server; - private final Map devicePositions = new ConcurrentHashMap<>(); + private final Map> devicePositions = new ConcurrentHashMap<>(); private final Map> deviceReferences = new ConcurrentHashMap<>(); @Inject @@ -97,7 +99,8 @@ public class CacheManager implements BroadcastInterface { } public Position getPosition(long deviceId) { - return devicePositions.get(deviceId); + var positions = devicePositions.get(deviceId); + return positions != null ? positions.peek() : null; } public Server getServer() { @@ -131,7 +134,9 @@ public class CacheManager implements BroadcastInterface { Position position = storage.getObject(Position.class, new Request( new Columns.All(), new Condition.Equals("id", device.getPositionId()))); if (position != null) { - devicePositions.put(deviceId, position); + devicePositions + .computeIfAbsent(deviceId, k -> new ConcurrentLinkedQueue<>()) + .add(position); } } } @@ -152,7 +157,11 @@ public class CacheManager implements BroadcastInterface { public void updatePosition(Position position) { deviceReferences.computeIfPresent(position.getDeviceId(), (key, oldValue) -> { - devicePositions.put(key, position); + var positions = devicePositions.computeIfAbsent(key, k -> new ConcurrentLinkedQueue<>()); + positions.add(position); + while (positions.size() > 1) { + positions.poll(); + } return oldValue; }); }