Commit 7ec6923451f6a2240f5e69af95b64e956b80fb1f
Committed by
GitHub
Merge pull request #4824 from YevhenBondarenko/feature/lwm2m-client-store
fetch all clients after startUp
Showing
9 changed files
with
86 additions
and
39 deletions
... | ... | @@ -269,7 +269,9 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor { |
269 | 269 | ToDeviceRpcRequestMetadata requestMd = toDeviceRpcPendingMap.remove(msg.getId()); |
270 | 270 | if (requestMd != null) { |
271 | 271 | log.debug("[{}] RPC request [{}] timeout detected!", deviceId, msg.getId()); |
272 | - systemContext.getTbRpcService().save(tenantId, new RpcId(requestMd.getMsg().getMsg().getId()), RpcStatus.TIMEOUT, null); | |
272 | + if (requestMd.getMsg().getMsg().isPersisted()) { | |
273 | + systemContext.getTbRpcService().save(tenantId, new RpcId(requestMd.getMsg().getMsg().getId()), RpcStatus.TIMEOUT, null); | |
274 | + } | |
273 | 275 | systemContext.getTbCoreDeviceRpcService().processRpcResponseFromDeviceActor(new FromDeviceRpcResponse(requestMd.getMsg().getMsg().getId(), |
274 | 276 | null, requestMd.isSent() ? RpcError.TIMEOUT : RpcError.NO_ACTIVE_CONNECTION)); |
275 | 277 | } | ... | ... |
... | ... | @@ -16,34 +16,24 @@ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.server; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.ObjectMapper; |
19 | -import com.google.gson.JsonObject; | |
20 | -import com.google.gson.JsonParser; | |
21 | -import com.google.gson.JsonSyntaxException; | |
22 | 19 | import lombok.extern.slf4j.Slf4j; |
23 | 20 | import org.apache.commons.lang3.StringUtils; |
24 | 21 | import org.eclipse.leshan.core.attributes.Attribute; |
25 | 22 | import org.eclipse.leshan.core.attributes.AttributeSet; |
26 | 23 | import org.eclipse.leshan.core.model.ObjectModel; |
27 | 24 | import org.eclipse.leshan.core.model.ResourceModel; |
28 | -import org.eclipse.leshan.core.node.LwM2mMultipleResource; | |
29 | -import org.eclipse.leshan.core.node.LwM2mNode; | |
30 | -import org.eclipse.leshan.core.node.LwM2mObject; | |
31 | -import org.eclipse.leshan.core.node.LwM2mObjectInstance; | |
32 | 25 | import org.eclipse.leshan.core.node.LwM2mPath; |
33 | 26 | import org.eclipse.leshan.core.node.LwM2mResource; |
34 | -import org.eclipse.leshan.core.node.LwM2mSingleResource; | |
35 | 27 | import org.eclipse.leshan.core.node.codec.CodecException; |
36 | 28 | import org.eclipse.leshan.core.request.SimpleDownlinkRequest; |
37 | 29 | import org.eclipse.leshan.core.request.WriteAttributesRequest; |
38 | 30 | import org.eclipse.leshan.core.util.Hex; |
39 | 31 | import org.eclipse.leshan.server.registration.Registration; |
40 | -import org.nustaq.serialization.FSTConfiguration; | |
41 | 32 | import org.thingsboard.server.common.data.DeviceProfile; |
42 | 33 | import org.thingsboard.server.common.data.DeviceTransportType; |
43 | 34 | import org.thingsboard.server.common.data.device.data.lwm2m.BootstrapConfiguration; |
44 | 35 | import org.thingsboard.server.common.data.device.profile.DeviceProfileTransportConfiguration; |
45 | 36 | import org.thingsboard.server.common.data.device.profile.Lwm2mDeviceProfileTransportConfiguration; |
46 | -import org.thingsboard.server.common.transport.TransportServiceCallback; | |
47 | 37 | import org.thingsboard.server.transport.lwm2m.config.LwM2mVersion; |
48 | 38 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
49 | 39 | import org.thingsboard.server.transport.lwm2m.server.client.ResourceValue; |
... | ... | @@ -56,10 +46,8 @@ import org.thingsboard.server.transport.lwm2m.server.uplink.DefaultLwM2MUplinkMs |
56 | 46 | import java.util.ArrayList; |
57 | 47 | import java.util.Arrays; |
58 | 48 | import java.util.Date; |
59 | -import java.util.LinkedList; | |
60 | 49 | import java.util.List; |
61 | 50 | import java.util.Map; |
62 | -import java.util.Optional; | |
63 | 51 | import java.util.concurrent.ConcurrentHashMap; |
64 | 52 | |
65 | 53 | import static org.eclipse.leshan.core.attributes.Attribute.DIMENSION; | ... | ... |
... | ... | @@ -23,9 +23,6 @@ import org.eclipse.leshan.core.model.ResourceModel; |
23 | 23 | import org.eclipse.leshan.core.node.LwM2mPath; |
24 | 24 | import org.eclipse.leshan.core.node.LwM2mResource; |
25 | 25 | import org.springframework.stereotype.Service; |
26 | -import org.thingsboard.server.common.data.ota.OtaPackageKey; | |
27 | -import org.thingsboard.server.common.data.ota.OtaPackageType; | |
28 | -import org.thingsboard.server.common.data.ota.OtaPackageUtil; | |
29 | 26 | import org.thingsboard.server.common.transport.TransportService; |
30 | 27 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
31 | 28 | import org.thingsboard.server.gen.transport.TransportProtos; | ... | ... |
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.server.client; |
17 | 17 | |
18 | +import lombok.EqualsAndHashCode; | |
18 | 19 | import lombok.Getter; |
19 | 20 | import lombok.Setter; |
20 | 21 | import lombok.extern.slf4j.Slf4j; |
... | ... | @@ -60,6 +61,7 @@ import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.f |
60 | 61 | import static org.thingsboard.server.transport.lwm2m.server.LwM2mTransportUtil.getVerFromPathIdVerOrId; |
61 | 62 | |
62 | 63 | @Slf4j |
64 | +@EqualsAndHashCode(of = {"endpoint"}) | |
63 | 65 | public class LwM2mClient implements Serializable { |
64 | 66 | |
65 | 67 | private static final long serialVersionUID = 8793482946289222623L; | ... | ... |
... | ... | @@ -32,6 +32,7 @@ import org.thingsboard.server.common.transport.TransportDeviceProfileCache; |
32 | 32 | import org.thingsboard.server.common.transport.TransportServiceCallback; |
33 | 33 | import org.thingsboard.server.common.transport.auth.ValidateDeviceCredentialsResponse; |
34 | 34 | import org.thingsboard.server.gen.transport.TransportProtos; |
35 | +import org.thingsboard.server.queue.util.AfterStartUp; | |
35 | 36 | import org.thingsboard.server.queue.util.TbLwM2mTransportComponent; |
36 | 37 | import org.thingsboard.server.transport.lwm2m.config.LwM2MTransportServerConfig; |
37 | 38 | import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo; |
... | ... | @@ -81,6 +82,17 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { |
81 | 82 | private final Map<String, LwM2mClient> lwM2mClientsByRegistrationId = new ConcurrentHashMap<>(); |
82 | 83 | private final Map<UUID, Lwm2mDeviceProfileTransportConfiguration> profiles = new ConcurrentHashMap<>(); |
83 | 84 | |
85 | + @AfterStartUp | |
86 | + public void init() { | |
87 | + String nodeId = context.getNodeId(); | |
88 | + Set<LwM2mClient> fetchedClients = clientStore.getAll(); | |
89 | + log.debug("Fetched clients from store: {}", fetchedClients); | |
90 | + fetchedClients.forEach(client -> { | |
91 | + lwM2mClientsByEndpoint.put(client.getEndpoint(), client); | |
92 | + updateFetchedClient(nodeId, client); | |
93 | + }); | |
94 | + } | |
95 | + | |
84 | 96 | @Override |
85 | 97 | public LwM2mClient getClientByEndpoint(String endpoint) { |
86 | 98 | return lwM2mClientsByEndpoint.computeIfAbsent(endpoint, ep -> { |
... | ... | @@ -91,23 +103,27 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { |
91 | 103 | client = new LwM2mClient(nodeId, ep); |
92 | 104 | } else { |
93 | 105 | log.debug("[{}] fetched client from store: {}", endpoint, client); |
94 | - boolean updated = false; | |
95 | - if (client.getRegistration() != null) { | |
96 | - lwM2mClientsByRegistrationId.put(client.getRegistration().getId(), client); | |
97 | - } | |
98 | - if (client.getSession() != null) { | |
99 | - client.refreshSessionId(nodeId); | |
100 | - sessionManager.register(client.getSession()); | |
101 | - updated = true; | |
102 | - } | |
103 | - if (updated) { | |
104 | - clientStore.put(client); | |
105 | - } | |
106 | + updateFetchedClient(nodeId, client); | |
106 | 107 | } |
107 | 108 | return client; |
108 | 109 | }); |
109 | 110 | } |
110 | 111 | |
112 | + private void updateFetchedClient(String nodeId, LwM2mClient client) { | |
113 | + boolean updated = false; | |
114 | + if (client.getRegistration() != null) { | |
115 | + lwM2mClientsByRegistrationId.put(client.getRegistration().getId(), client); | |
116 | + } | |
117 | + if (client.getSession() != null) { | |
118 | + client.refreshSessionId(nodeId); | |
119 | + sessionManager.register(client.getSession()); | |
120 | + updated = true; | |
121 | + } | |
122 | + if (updated) { | |
123 | + clientStore.put(client); | |
124 | + } | |
125 | + } | |
126 | + | |
111 | 127 | @Override |
112 | 128 | public Optional<TransportProtos.SessionInfoProto> register(LwM2mClient client, Registration registration) throws LwM2MClientStateException { |
113 | 129 | TransportProtos.SessionInfoProto oldSession = null; |
... | ... | @@ -282,22 +298,23 @@ public class LwM2mClientContextImpl implements LwM2mClientContext { |
282 | 298 | @Override |
283 | 299 | public Lwm2mDeviceProfileTransportConfiguration getProfile(Registration registration) { |
284 | 300 | UUID profileId = getClientByEndpoint(registration.getEndpoint()).getProfileId(); |
285 | - Lwm2mDeviceProfileTransportConfiguration result = doGetAndCache(profileId); | |
301 | + return doGetAndCache(profileId); | |
302 | + } | |
303 | + | |
304 | + private Lwm2mDeviceProfileTransportConfiguration doGetAndCache(UUID profileId) { | |
305 | + Lwm2mDeviceProfileTransportConfiguration result = profiles.get(profileId); | |
286 | 306 | if (result == null) { |
287 | - log.debug("[{}] Fetching profile [{}]", registration.getEndpoint(), profileId); | |
307 | + log.debug("Fetching profile [{}]", profileId); | |
288 | 308 | DeviceProfile deviceProfile = deviceProfileCache.get(new DeviceProfileId(profileId)); |
289 | 309 | if (deviceProfile != null) { |
290 | - profileUpdate(deviceProfile); | |
291 | - result = doGetAndCache(profileId); | |
310 | + result = profileUpdate(deviceProfile); | |
311 | + } else { | |
312 | + log.info("Device profile was not found! Most probably device profile [{}] has been removed from the database.", profileId); | |
292 | 313 | } |
293 | 314 | } |
294 | 315 | return result; |
295 | 316 | } |
296 | 317 | |
297 | - private Lwm2mDeviceProfileTransportConfiguration doGetAndCache(UUID profileId) { | |
298 | - return profiles.get(profileId); | |
299 | - } | |
300 | - | |
301 | 318 | @Override |
302 | 319 | public Lwm2mDeviceProfileTransportConfiguration profileUpdate(DeviceProfile deviceProfile) { |
303 | 320 | Lwm2mDeviceProfileTransportConfiguration clientProfile = LwM2mTransportUtil.toLwM2MClientProfile(deviceProfile); | ... | ... |
... | ... | @@ -17,6 +17,9 @@ package org.thingsboard.server.transport.lwm2m.server.store; |
17 | 17 | |
18 | 18 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
19 | 19 | |
20 | +import java.util.Collections; | |
21 | +import java.util.Set; | |
22 | + | |
20 | 23 | public class TbDummyLwM2MClientStore implements TbLwM2MClientStore { |
21 | 24 | @Override |
22 | 25 | public LwM2mClient get(String endpoint) { |
... | ... | @@ -24,6 +27,11 @@ public class TbDummyLwM2MClientStore implements TbLwM2MClientStore { |
24 | 27 | } |
25 | 28 | |
26 | 29 | @Override |
30 | + public Set<LwM2mClient> getAll() { | |
31 | + return Collections.emptySet(); | |
32 | + } | |
33 | + | |
34 | + @Override | |
27 | 35 | public void put(LwM2mClient client) { |
28 | 36 | |
29 | 37 | } | ... | ... |
... | ... | @@ -17,10 +17,14 @@ package org.thingsboard.server.transport.lwm2m.server.store; |
17 | 17 | |
18 | 18 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
19 | 19 | |
20 | +import java.util.Set; | |
21 | + | |
20 | 22 | public interface TbLwM2MClientStore { |
21 | 23 | |
22 | 24 | LwM2mClient get(String endpoint); |
23 | 25 | |
26 | + Set<LwM2mClient> getAll(); | |
27 | + | |
24 | 28 | void put(LwM2mClient client); |
25 | 29 | |
26 | 30 | void remove(String endpoint); | ... | ... |
... | ... | @@ -23,12 +23,9 @@ import org.thingsboard.server.transport.lwm2m.secure.LwM2mCredentialsSecurityInf |
23 | 23 | import org.thingsboard.server.transport.lwm2m.secure.TbLwM2MSecurityInfo; |
24 | 24 | |
25 | 25 | import java.util.HashSet; |
26 | -import java.util.Map; | |
27 | 26 | import java.util.Set; |
28 | 27 | import java.util.concurrent.ConcurrentHashMap; |
29 | 28 | import java.util.concurrent.ConcurrentMap; |
30 | -import java.util.concurrent.locks.Lock; | |
31 | -import java.util.concurrent.locks.ReentrantLock; | |
32 | 29 | |
33 | 30 | import static org.thingsboard.server.transport.lwm2m.server.uplink.LwM2mTypeServer.CLIENT; |
34 | 31 | ... | ... |
... | ... | @@ -16,9 +16,17 @@ |
16 | 16 | package org.thingsboard.server.transport.lwm2m.server.store; |
17 | 17 | |
18 | 18 | import org.nustaq.serialization.FSTConfiguration; |
19 | +import org.springframework.data.redis.connection.RedisClusterConnection; | |
19 | 20 | import org.springframework.data.redis.connection.RedisConnectionFactory; |
21 | +import org.springframework.data.redis.core.Cursor; | |
22 | +import org.springframework.data.redis.core.ScanOptions; | |
20 | 23 | import org.thingsboard.server.transport.lwm2m.server.client.LwM2mClient; |
21 | 24 | |
25 | +import java.util.ArrayList; | |
26 | +import java.util.HashSet; | |
27 | +import java.util.List; | |
28 | +import java.util.Set; | |
29 | + | |
22 | 30 | public class TbRedisLwM2MClientStore implements TbLwM2MClientStore { |
23 | 31 | |
24 | 32 | private static final String CLIENT_EP = "CLIENT#EP#"; |
... | ... | @@ -43,6 +51,30 @@ public class TbRedisLwM2MClientStore implements TbLwM2MClientStore { |
43 | 51 | } |
44 | 52 | |
45 | 53 | @Override |
54 | + public Set<LwM2mClient> getAll() { | |
55 | + try (var connection = connectionFactory.getConnection()) { | |
56 | + Set<LwM2mClient> clients = new HashSet<>(); | |
57 | + ScanOptions scanOptions = ScanOptions.scanOptions().count(100).match(CLIENT_EP + "*").build(); | |
58 | + List<Cursor<byte[]>> scans = new ArrayList<>(); | |
59 | + if (connection instanceof RedisClusterConnection) { | |
60 | + ((RedisClusterConnection) connection).clusterGetNodes().forEach(node -> { | |
61 | + scans.add(((RedisClusterConnection) connection).scan(node, scanOptions)); | |
62 | + }); | |
63 | + } else { | |
64 | + scans.add(connection.scan(scanOptions)); | |
65 | + } | |
66 | + | |
67 | + scans.forEach(scan -> { | |
68 | + scan.forEachRemaining(key -> { | |
69 | + byte[] element = connection.get(key); | |
70 | + clients.add((LwM2mClient) serializer.asObject(element)); | |
71 | + }); | |
72 | + }); | |
73 | + return clients; | |
74 | + } | |
75 | + } | |
76 | + | |
77 | + @Override | |
46 | 78 | public void put(LwM2mClient client) { |
47 | 79 | byte[] clientSerialized = serializer.asByteArray(client); |
48 | 80 | try (var connection = connectionFactory.getConnection()) { | ... | ... |