Commit fed0fe8b000a094d37a0a61da770c5485041e32a
1 parent
7b0b5e72
Redis cache as an option and adding Serializable.
Showing
25 changed files
with
486 additions
and
180 deletions
... | ... | @@ -429,12 +429,12 @@ public final class PluginProcessingContext implements PluginContext { |
429 | 429 | |
430 | 430 | @Override |
431 | 431 | public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) { |
432 | - return this.pluginCtx.relationService.findByFromAndType(from, relationType, RelationTypeGroup.COMMON); | |
432 | + return this.pluginCtx.relationService.findByFromAndTypeAsync(from, relationType, RelationTypeGroup.COMMON); | |
433 | 433 | } |
434 | 434 | |
435 | 435 | @Override |
436 | 436 | public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId from, String relationType) { |
437 | - return this.pluginCtx.relationService.findByToAndType(from, relationType, RelationTypeGroup.COMMON); | |
437 | + return this.pluginCtx.relationService.findByToAndTypeAsync(from, relationType, RelationTypeGroup.COMMON); | |
438 | 438 | } |
439 | 439 | |
440 | 440 | @Override | ... | ... |
... | ... | @@ -117,6 +117,10 @@ public abstract class BaseController { |
117 | 117 | @Autowired |
118 | 118 | protected RelationService relationService; |
119 | 119 | |
120 | + @ExceptionHandler(Exception.class) | |
121 | + public void handleException(Exception ex, HttpServletResponse response) { | |
122 | + errorResponseHandler.handle(ex, response); | |
123 | + } | |
120 | 124 | |
121 | 125 | @ExceptionHandler(ThingsboardException.class) |
122 | 126 | public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) { | ... | ... |
... | ... | @@ -120,7 +120,7 @@ public class EntityRelationController extends BaseController { |
120 | 120 | checkEntityId(fromId); |
121 | 121 | checkEntityId(toId); |
122 | 122 | RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); |
123 | - return checkNotNull(relationService.getRelation(fromId, toId, strRelationType, typeGroup).get()); | |
123 | + return checkNotNull(relationService.getRelation(fromId, toId, strRelationType, typeGroup)); | |
124 | 124 | } catch (Exception e) { |
125 | 125 | throw handleException(e); |
126 | 126 | } |
... | ... | @@ -138,7 +138,7 @@ public class EntityRelationController extends BaseController { |
138 | 138 | checkEntityId(entityId); |
139 | 139 | RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); |
140 | 140 | try { |
141 | - return checkNotNull(relationService.findByFrom(entityId, typeGroup).get()); | |
141 | + return checkNotNull(relationService.findByFrom(entityId, typeGroup)); | |
142 | 142 | } catch (Exception e) { |
143 | 143 | throw handleException(e); |
144 | 144 | } |
... | ... | @@ -176,7 +176,7 @@ public class EntityRelationController extends BaseController { |
176 | 176 | checkEntityId(entityId); |
177 | 177 | RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); |
178 | 178 | try { |
179 | - return checkNotNull(relationService.findByFromAndType(entityId, strRelationType, typeGroup).get()); | |
179 | + return checkNotNull(relationService.findByFromAndType(entityId, strRelationType, typeGroup)); | |
180 | 180 | } catch (Exception e) { |
181 | 181 | throw handleException(e); |
182 | 182 | } |
... | ... | @@ -194,7 +194,7 @@ public class EntityRelationController extends BaseController { |
194 | 194 | checkEntityId(entityId); |
195 | 195 | RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); |
196 | 196 | try { |
197 | - return checkNotNull(relationService.findByTo(entityId, typeGroup).get()); | |
197 | + return checkNotNull(relationService.findByTo(entityId, typeGroup)); | |
198 | 198 | } catch (Exception e) { |
199 | 199 | throw handleException(e); |
200 | 200 | } |
... | ... | @@ -232,7 +232,7 @@ public class EntityRelationController extends BaseController { |
232 | 232 | checkEntityId(entityId); |
233 | 233 | RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON); |
234 | 234 | try { |
235 | - return checkNotNull(relationService.findByToAndType(entityId, strRelationType, typeGroup).get()); | |
235 | + return checkNotNull(relationService.findByToAndType(entityId, strRelationType, typeGroup)); | |
236 | 236 | } catch (Exception e) { |
237 | 237 | throw handleException(e); |
238 | 238 | } | ... | ... |
... | ... | @@ -214,26 +214,11 @@ actors: |
214 | 214 | enabled: "${ACTORS_STATISTICS_ENABLED:true}" |
215 | 215 | persist_frequency: "${ACTORS_STATISTICS_PERSIST_FREQUENCY:3600000}" |
216 | 216 | |
217 | -# Cache parameters | |
218 | 217 | cache: |
219 | - # Enable/disable cache functionality. | |
220 | - enabled: "${CACHE_ENABLED:false}" | |
221 | - device_credentials: | |
222 | - # Default time to store device credentials in cache, in seconds | |
223 | - time_to_live: "${CACHE_DEVICE_CREDENTIAL_TTL:3600}" | |
224 | - # Maximum size of the map. When maximum size is reached, the map is evicted based on the policy defined. | |
225 | - max_size: | |
226 | - # Max size policy options: | |
227 | - # PER_NODE: Maximum number of map entries in each JVM. | |
228 | - # PER_PARTITION: Maximum number of map entries within each partition. | |
229 | - # USED_HEAP_SIZE: Maximum used heap size in megabytes for each JVM. | |
230 | - # USED_HEAP_PERCENTAGE: Maximum used heap size percentage for each JVM. | |
231 | - # FREE_HEAP_SIZE: Minimum free heap size in megabytes for each JVM. | |
232 | - # FREE_HEAP_PERCENTAGE: Minimum free heap size percentage for each JVM. | |
233 | - policy: "${CACHE_DEVICE_CREDENTIAL_MAX_SIZE_POLICY:PER_NODE}" | |
234 | - size: "${CACHE_DEVICE_CREDENTIAL_MAX_SIZE_SIZE:1000000}" | |
218 | + # caffeine or redis | |
219 | + type: "${CACHE_TYPE:caffeine}" | |
235 | 220 | |
236 | -caching: | |
221 | +caffeine: | |
237 | 222 | specs: |
238 | 223 | relations: |
239 | 224 | timeToLiveInMinutes: 1440 |
... | ... | @@ -245,6 +230,15 @@ caching: |
245 | 230 | timeToLiveInMinutes: 1440 |
246 | 231 | maxSize: 100000 |
247 | 232 | |
233 | +redis: | |
234 | + # standalone or cluster | |
235 | + connection: | |
236 | + type: standalone | |
237 | + host: "${REDIS_HOST:localhost}" | |
238 | + port: "${REDIS_PORT:6379}" | |
239 | + db: "${REDIS_DB:0}" | |
240 | + password: "${REDIS_PASSWORD:}" | |
241 | + | |
248 | 242 | # Check new version updates parameters |
249 | 243 | updates: |
250 | 244 | # Enable/disable updates checking. | ... | ... |
... | ... | @@ -19,7 +19,7 @@ import lombok.EqualsAndHashCode; |
19 | 19 | import org.thingsboard.server.common.data.id.UUIDBased; |
20 | 20 | |
21 | 21 | @EqualsAndHashCode(callSuper = true) |
22 | -public abstract class ContactBased<I extends UUIDBased> extends SearchTextBased<I> { | |
22 | +public abstract class ContactBased<I extends UUIDBased> extends SearchTextBasedWithAdditionalInfo<I> { | |
23 | 23 | |
24 | 24 | private static final long serialVersionUID = 5047448057830660988L; |
25 | 25 | ... | ... |
... | ... | @@ -29,8 +29,7 @@ public class Customer extends ContactBased<CustomerId> implements HasName { |
29 | 29 | |
30 | 30 | private String title; |
31 | 31 | private TenantId tenantId; |
32 | - private transient JsonNode additionalInfo; | |
33 | - | |
32 | + | |
34 | 33 | public Customer() { |
35 | 34 | super(); |
36 | 35 | } |
... | ... | @@ -43,7 +42,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName { |
43 | 42 | super(customer); |
44 | 43 | this.tenantId = customer.getTenantId(); |
45 | 44 | this.title = customer.getTitle(); |
46 | - this.additionalInfo = customer.getAdditionalInfo(); | |
47 | 45 | } |
48 | 46 | |
49 | 47 | public TenantId getTenantId() { |
... | ... | @@ -65,7 +63,7 @@ public class Customer extends ContactBased<CustomerId> implements HasName { |
65 | 63 | @JsonIgnore |
66 | 64 | public boolean isPublic() { |
67 | 65 | if (getAdditionalInfo() != null && getAdditionalInfo().has("isPublic")) { |
68 | - return additionalInfo.get("isPublic").asBoolean(); | |
66 | + return getAdditionalInfo().get("isPublic").asBoolean(); | |
69 | 67 | } |
70 | 68 | |
71 | 69 | return false; |
... | ... | @@ -77,14 +75,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName { |
77 | 75 | return title; |
78 | 76 | } |
79 | 77 | |
80 | - public JsonNode getAdditionalInfo() { | |
81 | - return additionalInfo; | |
82 | - } | |
83 | - | |
84 | - public void setAdditionalInfo(JsonNode additionalInfo) { | |
85 | - this.additionalInfo = additionalInfo; | |
86 | - } | |
87 | - | |
88 | 78 | @Override |
89 | 79 | public String getSearchText() { |
90 | 80 | return getTitle(); |
... | ... | @@ -94,7 +84,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName { |
94 | 84 | public int hashCode() { |
95 | 85 | final int prime = 31; |
96 | 86 | int result = super.hashCode(); |
97 | - result = prime * result + ((additionalInfo == null) ? 0 : additionalInfo.hashCode()); | |
98 | 87 | result = prime * result + ((tenantId == null) ? 0 : tenantId.hashCode()); |
99 | 88 | result = prime * result + ((title == null) ? 0 : title.hashCode()); |
100 | 89 | return result; |
... | ... | @@ -109,11 +98,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName { |
109 | 98 | if (getClass() != obj.getClass()) |
110 | 99 | return false; |
111 | 100 | Customer other = (Customer) obj; |
112 | - if (additionalInfo == null) { | |
113 | - if (other.additionalInfo != null) | |
114 | - return false; | |
115 | - } else if (!additionalInfo.equals(other.additionalInfo)) | |
116 | - return false; | |
117 | 101 | if (tenantId == null) { |
118 | 102 | if (other.tenantId != null) |
119 | 103 | return false; |
... | ... | @@ -135,7 +119,7 @@ public class Customer extends ContactBased<CustomerId> implements HasName { |
135 | 119 | builder.append(", tenantId="); |
136 | 120 | builder.append(tenantId); |
137 | 121 | builder.append(", additionalInfo="); |
138 | - builder.append(additionalInfo); | |
122 | + builder.append(getAdditionalInfo()); | |
139 | 123 | builder.append(", country="); |
140 | 124 | builder.append(country); |
141 | 125 | builder.append(", state="); | ... | ... |
... | ... | @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId; |
23 | 23 | import com.fasterxml.jackson.databind.JsonNode; |
24 | 24 | |
25 | 25 | @EqualsAndHashCode(callSuper = true) |
26 | -public class Device extends SearchTextBased<DeviceId> implements HasName { | |
26 | +public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName { | |
27 | 27 | |
28 | 28 | private static final long serialVersionUID = 2807343040519543363L; |
29 | 29 | |
... | ... | @@ -31,7 +31,6 @@ public class Device extends SearchTextBased<DeviceId> implements HasName { |
31 | 31 | private CustomerId customerId; |
32 | 32 | private String name; |
33 | 33 | private String type; |
34 | - private transient JsonNode additionalInfo; | |
35 | 34 | |
36 | 35 | public Device() { |
37 | 36 | super(); |
... | ... | @@ -47,7 +46,6 @@ public class Device extends SearchTextBased<DeviceId> implements HasName { |
47 | 46 | this.customerId = device.getCustomerId(); |
48 | 47 | this.name = device.getName(); |
49 | 48 | this.type = device.getType(); |
50 | - this.additionalInfo = device.getAdditionalInfo(); | |
51 | 49 | } |
52 | 50 | |
53 | 51 | public TenantId getTenantId() { |
... | ... | @@ -83,14 +81,6 @@ public class Device extends SearchTextBased<DeviceId> implements HasName { |
83 | 81 | this.type = type; |
84 | 82 | } |
85 | 83 | |
86 | - public JsonNode getAdditionalInfo() { | |
87 | - return additionalInfo; | |
88 | - } | |
89 | - | |
90 | - public void setAdditionalInfo(JsonNode additionalInfo) { | |
91 | - this.additionalInfo = additionalInfo; | |
92 | - } | |
93 | - | |
94 | 84 | @Override |
95 | 85 | public String getSearchText() { |
96 | 86 | return getName(); |
... | ... | @@ -108,7 +98,7 @@ public class Device extends SearchTextBased<DeviceId> implements HasName { |
108 | 98 | builder.append(", type="); |
109 | 99 | builder.append(type); |
110 | 100 | builder.append(", additionalInfo="); |
111 | - builder.append(additionalInfo); | |
101 | + builder.append(getAdditionalInfo()); | |
112 | 102 | builder.append(", createdTime="); |
113 | 103 | builder.append(createdTime); |
114 | 104 | builder.append(", id="); | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data; | |
17 | + | |
18 | +import com.fasterxml.jackson.databind.JsonNode; | |
19 | + | |
20 | +public interface HasAdditionalInfo { | |
21 | + | |
22 | + JsonNode getAdditionalInfo(); | |
23 | + | |
24 | +} | ... | ... |
common/data/src/main/java/org/thingsboard/server/common/data/SearchTextBasedWithAdditionalInfo.java
0 → 100644
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.common.data; | |
17 | + | |
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
19 | +import com.fasterxml.jackson.core.JsonProcessingException; | |
20 | +import com.fasterxml.jackson.databind.JsonNode; | |
21 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
22 | +import lombok.extern.slf4j.Slf4j; | |
23 | +import org.thingsboard.server.common.data.id.UUIDBased; | |
24 | + | |
25 | +import java.io.ByteArrayInputStream; | |
26 | +import java.io.IOException; | |
27 | +import java.util.Arrays; | |
28 | +import java.util.Objects; | |
29 | +import java.util.function.Supplier; | |
30 | +import java.util.function.Consumer; | |
31 | + | |
32 | +/** | |
33 | + * Created by ashvayka on 19.02.18. | |
34 | + */ | |
35 | +@Slf4j | |
36 | +public abstract class SearchTextBasedWithAdditionalInfo<I extends UUIDBased> extends SearchTextBased<I> implements HasAdditionalInfo { | |
37 | + | |
38 | + private transient JsonNode additionalInfo; | |
39 | + @JsonIgnore | |
40 | + private byte[] additionalInfoBytes; | |
41 | + | |
42 | + public SearchTextBasedWithAdditionalInfo() { | |
43 | + super(); | |
44 | + } | |
45 | + | |
46 | + public SearchTextBasedWithAdditionalInfo(I id) { | |
47 | + super(id); | |
48 | + } | |
49 | + | |
50 | + public SearchTextBasedWithAdditionalInfo(SearchTextBasedWithAdditionalInfo<I> searchTextBased) { | |
51 | + super(searchTextBased); | |
52 | + setAdditionalInfo(searchTextBased.getAdditionalInfo()); | |
53 | + } | |
54 | + | |
55 | + @Override | |
56 | + public JsonNode getAdditionalInfo() { | |
57 | + return getJson(() -> additionalInfo, () -> additionalInfoBytes); | |
58 | + } | |
59 | + | |
60 | + public void setAdditionalInfo(JsonNode addInfo) { | |
61 | + setJson(addInfo, json -> this.additionalInfo = json, bytes -> this.additionalInfoBytes = bytes); | |
62 | + } | |
63 | + | |
64 | + @Override | |
65 | + public boolean equals(Object o) { | |
66 | + if (this == o) return true; | |
67 | + if (o == null || getClass() != o.getClass()) return false; | |
68 | + if (!super.equals(o)) return false; | |
69 | + SearchTextBasedWithAdditionalInfo<?> that = (SearchTextBasedWithAdditionalInfo<?>) o; | |
70 | + return Arrays.equals(additionalInfoBytes, that.additionalInfoBytes); | |
71 | + } | |
72 | + | |
73 | + @Override | |
74 | + public int hashCode() { | |
75 | + return Objects.hash(super.hashCode(), additionalInfoBytes); | |
76 | + } | |
77 | + | |
78 | + public static JsonNode getJson(Supplier<JsonNode> jsonData, Supplier<byte[]> binaryData) { | |
79 | + JsonNode json = jsonData.get(); | |
80 | + if (json != null) { | |
81 | + return json; | |
82 | + } else { | |
83 | + byte[] data = binaryData.get(); | |
84 | + if (data != null) { | |
85 | + try { | |
86 | + return new ObjectMapper().readTree(new ByteArrayInputStream(data)); | |
87 | + } catch (IOException e) { | |
88 | + log.warn("Can't deserialize json data: ", e); | |
89 | + return null; | |
90 | + } | |
91 | + } else { | |
92 | + return null; | |
93 | + } | |
94 | + } | |
95 | + } | |
96 | + | |
97 | + public static void setJson(JsonNode json, Consumer<JsonNode> jsonConsumer, Consumer<byte[]> bytesConsumer) { | |
98 | + jsonConsumer.accept(json); | |
99 | + try { | |
100 | + bytesConsumer.accept(new ObjectMapper().writeValueAsBytes(json)); | |
101 | + } catch (JsonProcessingException e) { | |
102 | + log.warn("Can't serialize json data: ", e); | |
103 | + } | |
104 | + } | |
105 | +} | ... | ... |
... | ... | @@ -28,8 +28,7 @@ public class Tenant extends ContactBased<TenantId> implements HasName { |
28 | 28 | |
29 | 29 | private String title; |
30 | 30 | private String region; |
31 | - private transient JsonNode additionalInfo; | |
32 | - | |
31 | + | |
33 | 32 | public Tenant() { |
34 | 33 | super(); |
35 | 34 | } |
... | ... | @@ -42,7 +41,6 @@ public class Tenant extends ContactBased<TenantId> implements HasName { |
42 | 41 | super(tenant); |
43 | 42 | this.title = tenant.getTitle(); |
44 | 43 | this.region = tenant.getRegion(); |
45 | - this.additionalInfo = tenant.getAdditionalInfo(); | |
46 | 44 | } |
47 | 45 | |
48 | 46 | public String getTitle() { |
... | ... | @@ -67,14 +65,6 @@ public class Tenant extends ContactBased<TenantId> implements HasName { |
67 | 65 | this.region = region; |
68 | 66 | } |
69 | 67 | |
70 | - public JsonNode getAdditionalInfo() { | |
71 | - return additionalInfo; | |
72 | - } | |
73 | - | |
74 | - public void setAdditionalInfo(JsonNode additionalInfo) { | |
75 | - this.additionalInfo = additionalInfo; | |
76 | - } | |
77 | - | |
78 | 68 | @Override |
79 | 69 | public String getSearchText() { |
80 | 70 | return getTitle(); |
... | ... | @@ -88,7 +78,7 @@ public class Tenant extends ContactBased<TenantId> implements HasName { |
88 | 78 | builder.append(", region="); |
89 | 79 | builder.append(region); |
90 | 80 | builder.append(", additionalInfo="); |
91 | - builder.append(additionalInfo); | |
81 | + builder.append(getAdditionalInfo()); | |
92 | 82 | builder.append(", country="); |
93 | 83 | builder.append(country); |
94 | 84 | builder.append(", state="); | ... | ... |
... | ... | @@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.security.Authority; |
25 | 25 | import com.fasterxml.jackson.databind.JsonNode; |
26 | 26 | |
27 | 27 | @EqualsAndHashCode(callSuper = true) |
28 | -public class User extends SearchTextBased<UserId> implements HasName { | |
28 | +public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements HasName { | |
29 | 29 | |
30 | 30 | private static final long serialVersionUID = 8250339805336035966L; |
31 | 31 | |
... | ... | @@ -35,7 +35,6 @@ public class User extends SearchTextBased<UserId> implements HasName { |
35 | 35 | private Authority authority; |
36 | 36 | private String firstName; |
37 | 37 | private String lastName; |
38 | - private transient JsonNode additionalInfo; | |
39 | 38 | |
40 | 39 | public User() { |
41 | 40 | super(); |
... | ... | @@ -53,7 +52,6 @@ public class User extends SearchTextBased<UserId> implements HasName { |
53 | 52 | this.authority = user.getAuthority(); |
54 | 53 | this.firstName = user.getFirstName(); |
55 | 54 | this.lastName = user.getLastName(); |
56 | - this.additionalInfo = user.getAdditionalInfo(); | |
57 | 55 | } |
58 | 56 | |
59 | 57 | public TenantId getTenantId() { |
... | ... | @@ -110,14 +108,6 @@ public class User extends SearchTextBased<UserId> implements HasName { |
110 | 108 | this.lastName = lastName; |
111 | 109 | } |
112 | 110 | |
113 | - public JsonNode getAdditionalInfo() { | |
114 | - return additionalInfo; | |
115 | - } | |
116 | - | |
117 | - public void setAdditionalInfo(JsonNode additionalInfo) { | |
118 | - this.additionalInfo = additionalInfo; | |
119 | - } | |
120 | - | |
121 | 111 | @Override |
122 | 112 | public String getSearchText() { |
123 | 113 | return getEmail(); |
... | ... | @@ -139,7 +129,7 @@ public class User extends SearchTextBased<UserId> implements HasName { |
139 | 129 | builder.append(", lastName="); |
140 | 130 | builder.append(lastName); |
141 | 131 | builder.append(", additionalInfo="); |
142 | - builder.append(additionalInfo); | |
132 | + builder.append(getAdditionalInfo()); | |
143 | 133 | builder.append(", createdTime="); |
144 | 134 | builder.append(createdTime); |
145 | 135 | builder.append(", id="); | ... | ... |
... | ... | @@ -17,14 +17,16 @@ package org.thingsboard.server.common.data.asset; |
17 | 17 | |
18 | 18 | import com.fasterxml.jackson.databind.JsonNode; |
19 | 19 | import lombok.EqualsAndHashCode; |
20 | +import org.thingsboard.server.common.data.HasAdditionalInfo; | |
20 | 21 | import org.thingsboard.server.common.data.HasName; |
21 | 22 | import org.thingsboard.server.common.data.SearchTextBased; |
23 | +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | |
22 | 24 | import org.thingsboard.server.common.data.id.AssetId; |
23 | 25 | import org.thingsboard.server.common.data.id.CustomerId; |
24 | 26 | import org.thingsboard.server.common.data.id.TenantId; |
25 | 27 | |
26 | 28 | @EqualsAndHashCode(callSuper = true) |
27 | -public class Asset extends SearchTextBased<AssetId> implements HasName { | |
29 | +public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements HasName { | |
28 | 30 | |
29 | 31 | private static final long serialVersionUID = 2807343040519543363L; |
30 | 32 | |
... | ... | @@ -32,7 +34,6 @@ public class Asset extends SearchTextBased<AssetId> implements HasName { |
32 | 34 | private CustomerId customerId; |
33 | 35 | private String name; |
34 | 36 | private String type; |
35 | - private transient JsonNode additionalInfo; | |
36 | 37 | |
37 | 38 | public Asset() { |
38 | 39 | super(); |
... | ... | @@ -48,7 +49,6 @@ public class Asset extends SearchTextBased<AssetId> implements HasName { |
48 | 49 | this.customerId = asset.getCustomerId(); |
49 | 50 | this.name = asset.getName(); |
50 | 51 | this.type = asset.getType(); |
51 | - this.additionalInfo = asset.getAdditionalInfo(); | |
52 | 52 | } |
53 | 53 | |
54 | 54 | public TenantId getTenantId() { |
... | ... | @@ -84,14 +84,6 @@ public class Asset extends SearchTextBased<AssetId> implements HasName { |
84 | 84 | this.type = type; |
85 | 85 | } |
86 | 86 | |
87 | - public JsonNode getAdditionalInfo() { | |
88 | - return additionalInfo; | |
89 | - } | |
90 | - | |
91 | - public void setAdditionalInfo(JsonNode additionalInfo) { | |
92 | - this.additionalInfo = additionalInfo; | |
93 | - } | |
94 | - | |
95 | 87 | @Override |
96 | 88 | public String getSearchText() { |
97 | 89 | return getName(); |
... | ... | @@ -109,7 +101,7 @@ public class Asset extends SearchTextBased<AssetId> implements HasName { |
109 | 101 | builder.append(", type="); |
110 | 102 | builder.append(type); |
111 | 103 | builder.append(", additionalInfo="); |
112 | - builder.append(additionalInfo); | |
104 | + builder.append(getAdditionalInfo()); | |
113 | 105 | builder.append(", createdTime="); |
114 | 106 | builder.append(createdTime); |
115 | 107 | builder.append(", id="); | ... | ... |
... | ... | @@ -15,16 +15,24 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.data.plugin; |
17 | 17 | |
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
19 | +import com.fasterxml.jackson.core.JsonProcessingException; | |
20 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
18 | 21 | import lombok.EqualsAndHashCode; |
22 | +import lombok.extern.slf4j.Slf4j; | |
19 | 23 | import org.thingsboard.server.common.data.HasName; |
20 | -import org.thingsboard.server.common.data.SearchTextBased; | |
24 | +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | |
21 | 25 | import org.thingsboard.server.common.data.id.PluginId; |
22 | 26 | import org.thingsboard.server.common.data.id.TenantId; |
23 | 27 | |
24 | 28 | import com.fasterxml.jackson.databind.JsonNode; |
25 | 29 | |
30 | +import java.io.ByteArrayInputStream; | |
31 | +import java.io.IOException; | |
32 | + | |
26 | 33 | @EqualsAndHashCode(callSuper = true) |
27 | -public class PluginMetaData extends SearchTextBased<PluginId> implements HasName { | |
34 | +@Slf4j | |
35 | +public class PluginMetaData extends SearchTextBasedWithAdditionalInfo<PluginId> implements HasName { | |
28 | 36 | |
29 | 37 | private static final long serialVersionUID = 1L; |
30 | 38 | |
... | ... | @@ -35,7 +43,9 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName |
35 | 43 | private boolean publicAccess; |
36 | 44 | private ComponentLifecycleState state; |
37 | 45 | private transient JsonNode configuration; |
38 | - private transient JsonNode additionalInfo; | |
46 | + @JsonIgnore | |
47 | + private byte[] configurationBytes; | |
48 | + | |
39 | 49 | |
40 | 50 | public PluginMetaData() { |
41 | 51 | super(); |
... | ... | @@ -54,7 +64,6 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName |
54 | 64 | this.publicAccess = plugin.isPublicAccess(); |
55 | 65 | this.state = plugin.getState(); |
56 | 66 | this.configuration = plugin.getConfiguration(); |
57 | - this.additionalInfo = plugin.getAdditionalInfo(); | |
58 | 67 | } |
59 | 68 | |
60 | 69 | @Override |
... | ... | @@ -96,11 +105,11 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName |
96 | 105 | } |
97 | 106 | |
98 | 107 | public JsonNode getConfiguration() { |
99 | - return configuration; | |
108 | + return getJson(() -> configuration, () -> configurationBytes); | |
100 | 109 | } |
101 | 110 | |
102 | - public void setConfiguration(JsonNode configuration) { | |
103 | - this.configuration = configuration; | |
111 | + public void setConfiguration(JsonNode data) { | |
112 | + setJson(data, json -> this.configuration = json, bytes -> this.configurationBytes = bytes); | |
104 | 113 | } |
105 | 114 | |
106 | 115 | public boolean isPublicAccess() { |
... | ... | @@ -119,14 +128,6 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName |
119 | 128 | return state; |
120 | 129 | } |
121 | 130 | |
122 | - public JsonNode getAdditionalInfo() { | |
123 | - return additionalInfo; | |
124 | - } | |
125 | - | |
126 | - public void setAdditionalInfo(JsonNode additionalInfo) { | |
127 | - this.additionalInfo = additionalInfo; | |
128 | - } | |
129 | - | |
130 | 131 | @Override |
131 | 132 | public String toString() { |
132 | 133 | return "PluginMetaData [apiToken=" + apiToken + ", tenantId=" + tenantId + ", name=" + name + ", clazz=" + clazz + ", publicAccess=" + publicAccess | ... | ... |
... | ... | @@ -15,10 +15,20 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.data.relation; |
17 | 17 | |
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
19 | +import com.fasterxml.jackson.core.JsonProcessingException; | |
18 | 20 | import com.fasterxml.jackson.databind.JsonNode; |
21 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
22 | +import lombok.extern.slf4j.Slf4j; | |
23 | +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | |
19 | 24 | import org.thingsboard.server.common.data.id.EntityId; |
20 | 25 | |
21 | -public class EntityRelation { | |
26 | +import java.io.ByteArrayInputStream; | |
27 | +import java.io.IOException; | |
28 | +import java.io.Serializable; | |
29 | + | |
30 | +@Slf4j | |
31 | +public class EntityRelation implements Serializable { | |
22 | 32 | |
23 | 33 | private static final long serialVersionUID = 2807343040519543363L; |
24 | 34 | |
... | ... | @@ -29,7 +39,9 @@ public class EntityRelation { |
29 | 39 | private EntityId to; |
30 | 40 | private String type; |
31 | 41 | private RelationTypeGroup typeGroup; |
32 | - private JsonNode additionalInfo; | |
42 | + private transient JsonNode additionalInfo; | |
43 | + @JsonIgnore | |
44 | + private byte[] additionalInfoBytes; | |
33 | 45 | |
34 | 46 | public EntityRelation() { |
35 | 47 | super(); |
... | ... | @@ -92,11 +104,11 @@ public class EntityRelation { |
92 | 104 | } |
93 | 105 | |
94 | 106 | public JsonNode getAdditionalInfo() { |
95 | - return additionalInfo; | |
107 | + return SearchTextBasedWithAdditionalInfo.getJson(() -> additionalInfo, () -> additionalInfoBytes); | |
96 | 108 | } |
97 | 109 | |
98 | - public void setAdditionalInfo(JsonNode additionalInfo) { | |
99 | - this.additionalInfo = additionalInfo; | |
110 | + public void setAdditionalInfo(JsonNode addInfo) { | |
111 | + SearchTextBasedWithAdditionalInfo.setJson(addInfo, json -> this.additionalInfo = json, bytes -> this.additionalInfoBytes = bytes); | |
100 | 112 | } |
101 | 113 | |
102 | 114 | @Override | ... | ... |
... | ... | @@ -15,18 +15,23 @@ |
15 | 15 | */ |
16 | 16 | package org.thingsboard.server.common.data.rule; |
17 | 17 | |
18 | +import com.fasterxml.jackson.annotation.JsonIgnore; | |
19 | +import com.fasterxml.jackson.core.JsonProcessingException; | |
18 | 20 | import com.fasterxml.jackson.databind.JsonNode; |
21 | +import com.fasterxml.jackson.databind.ObjectMapper; | |
19 | 22 | import lombok.Data; |
20 | 23 | import lombok.EqualsAndHashCode; |
24 | +import lombok.extern.slf4j.Slf4j; | |
21 | 25 | import org.thingsboard.server.common.data.HasName; |
22 | -import org.thingsboard.server.common.data.SearchTextBased; | |
26 | +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo; | |
23 | 27 | import org.thingsboard.server.common.data.id.RuleId; |
24 | 28 | import org.thingsboard.server.common.data.id.TenantId; |
25 | 29 | import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; |
26 | 30 | |
27 | 31 | @Data |
28 | 32 | @EqualsAndHashCode(callSuper = true) |
29 | -public class RuleMetaData extends SearchTextBased<RuleId> implements HasName { | |
33 | +@Slf4j | |
34 | +public class RuleMetaData extends SearchTextBasedWithAdditionalInfo<RuleId> implements HasName { | |
30 | 35 | |
31 | 36 | private static final long serialVersionUID = -5656679015122935465L; |
32 | 37 | |
... | ... | @@ -38,7 +43,13 @@ public class RuleMetaData extends SearchTextBased<RuleId> implements HasName { |
38 | 43 | private transient JsonNode filters; |
39 | 44 | private transient JsonNode processor; |
40 | 45 | private transient JsonNode action; |
41 | - private transient JsonNode additionalInfo; | |
46 | + @JsonIgnore | |
47 | + private byte[] filtersBytes; | |
48 | + @JsonIgnore | |
49 | + private byte[] processorBytes; | |
50 | + @JsonIgnore | |
51 | + private byte[] actionBytes; | |
52 | + | |
42 | 53 | |
43 | 54 | public RuleMetaData() { |
44 | 55 | super(); |
... | ... | @@ -55,10 +66,9 @@ public class RuleMetaData extends SearchTextBased<RuleId> implements HasName { |
55 | 66 | this.state = rule.getState(); |
56 | 67 | this.weight = rule.getWeight(); |
57 | 68 | this.pluginToken = rule.getPluginToken(); |
58 | - this.filters = rule.getFilters(); | |
59 | - this.processor = rule.getProcessor(); | |
60 | - this.action = rule.getAction(); | |
61 | - this.additionalInfo = rule.getAdditionalInfo(); | |
69 | + this.setFilters(rule.getFilters()); | |
70 | + this.setProcessor(rule.getProcessor()); | |
71 | + this.setAction(rule.getAction()); | |
62 | 72 | } |
63 | 73 | |
64 | 74 | @Override |
... | ... | @@ -71,4 +81,29 @@ public class RuleMetaData extends SearchTextBased<RuleId> implements HasName { |
71 | 81 | return name; |
72 | 82 | } |
73 | 83 | |
84 | + public JsonNode getFilters() { | |
85 | + return SearchTextBasedWithAdditionalInfo.getJson(() -> filters, () -> filtersBytes); | |
86 | + } | |
87 | + | |
88 | + public JsonNode getProcessor() { | |
89 | + return SearchTextBasedWithAdditionalInfo.getJson(() -> processor, () -> processorBytes); | |
90 | + } | |
91 | + | |
92 | + public JsonNode getAction() { | |
93 | + return SearchTextBasedWithAdditionalInfo.getJson(() -> action, () -> actionBytes); | |
94 | + } | |
95 | + | |
96 | + public void setFilters(JsonNode data) { | |
97 | + setJson(data, json -> this.filters = json, bytes -> this.filtersBytes = bytes); | |
98 | + } | |
99 | + | |
100 | + public void setProcessor(JsonNode data) { | |
101 | + setJson(data, json -> this.processor = json, bytes -> this.processorBytes = bytes); | |
102 | + } | |
103 | + | |
104 | + public void setAction(JsonNode data) { | |
105 | + setJson(data, json -> this.action = json, bytes -> this.actionBytes = bytes); | |
106 | + } | |
107 | + | |
108 | + | |
74 | 109 | } | ... | ... |
... | ... | @@ -182,6 +182,14 @@ |
182 | 182 | <groupId>org.springframework</groupId> |
183 | 183 | <artifactId>spring-context-support</artifactId> |
184 | 184 | </dependency> |
185 | + <dependency> | |
186 | + <groupId>org.springframework.data</groupId> | |
187 | + <artifactId>spring-data-redis</artifactId> | |
188 | + </dependency> | |
189 | + <dependency> | |
190 | + <groupId>redis.clients</groupId> | |
191 | + <artifactId>jedis</artifactId> | |
192 | + </dependency> | |
185 | 193 | </dependencies> |
186 | 194 | <build> |
187 | 195 | <plugins> | ... | ... |
... | ... | @@ -337,7 +337,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ |
337 | 337 | |
338 | 338 | private void updateRelations(Alarm alarm, AlarmStatus oldStatus, AlarmStatus newStatus) { |
339 | 339 | try { |
340 | - List<EntityRelation> relations = relationService.findByTo(alarm.getId(), RelationTypeGroup.ALARM).get(); | |
340 | + List<EntityRelation> relations = relationService.findByToAsync(alarm.getId(), RelationTypeGroup.ALARM).get(); | |
341 | 341 | Set<EntityId> parents = relations.stream().map(EntityRelation::getFrom).collect(Collectors.toSet()); |
342 | 342 | for (EntityId parentId : parents) { |
343 | 343 | updateAlarmRelation(parentId, alarm.getId(), oldStatus, newStatus); | ... | ... |
dao/src/main/java/org/thingsboard/server/dao/cache/CaffeineCacheConfiguration.java
renamed from
dao/src/main/java/org/thingsboard/server/dao/cache/ServiceCacheConfiguration.java
... | ... | @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.cache; |
18 | 18 | import com.github.benmanes.caffeine.cache.Caffeine; |
19 | 19 | import com.github.benmanes.caffeine.cache.Ticker; |
20 | 20 | import lombok.Data; |
21 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |
21 | 22 | import org.springframework.boot.context.properties.ConfigurationProperties; |
22 | 23 | import org.springframework.cache.CacheManager; |
23 | 24 | import org.springframework.cache.annotation.EnableCaching; |
... | ... | @@ -33,10 +34,11 @@ import java.util.concurrent.TimeUnit; |
33 | 34 | import java.util.stream.Collectors; |
34 | 35 | |
35 | 36 | @Configuration |
36 | -@ConfigurationProperties(prefix = "caching") | |
37 | +@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true) | |
38 | +@ConfigurationProperties(prefix = "caffeine") | |
37 | 39 | @EnableCaching |
38 | 40 | @Data |
39 | -public class ServiceCacheConfiguration { | |
41 | +public class CaffeineCacheConfiguration { | |
40 | 42 | |
41 | 43 | private Map<String, CacheSpecs> specs; |
42 | 44 | ... | ... |
1 | +/** | |
2 | + * Copyright © 2016-2017 The Thingsboard Authors | |
3 | + * | |
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | + * you may not use this file except in compliance with the License. | |
6 | + * You may obtain a copy of the License at | |
7 | + * | |
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | |
9 | + * | |
10 | + * Unless required by applicable law or agreed to in writing, software | |
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | + * See the License for the specific language governing permissions and | |
14 | + * limitations under the License. | |
15 | + */ | |
16 | +package org.thingsboard.server.dao.cache; | |
17 | + | |
18 | +import lombok.Data; | |
19 | +import org.springframework.beans.factory.annotation.Value; | |
20 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | |
21 | +import org.springframework.boot.context.properties.ConfigurationProperties; | |
22 | +import org.springframework.cache.CacheManager; | |
23 | +import org.springframework.cache.annotation.EnableCaching; | |
24 | +import org.springframework.cache.interceptor.KeyGenerator; | |
25 | +import org.springframework.context.annotation.Bean; | |
26 | +import org.springframework.context.annotation.Configuration; | |
27 | +import org.springframework.data.redis.cache.RedisCacheManager; | |
28 | +import org.springframework.data.redis.connection.RedisConnectionFactory; | |
29 | +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; | |
30 | +import org.springframework.data.redis.core.RedisTemplate; | |
31 | + | |
32 | +@Configuration | |
33 | +@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis", matchIfMissing = false) | |
34 | +@EnableCaching | |
35 | +@Data | |
36 | +public class TBRedisCacheConfiguration { | |
37 | + | |
38 | + @Value("${redis.connection.host}") | |
39 | + private String host; | |
40 | + | |
41 | + @Value("${redis.connection.port}") | |
42 | + private Integer port; | |
43 | + | |
44 | + @Value("${redis.connection.db}") | |
45 | + private Integer db; | |
46 | + | |
47 | + @Value("${redis.connection.password}") | |
48 | + private String password; | |
49 | + | |
50 | + @Bean | |
51 | + public RedisConnectionFactory redisConnectionFactory() { | |
52 | + JedisConnectionFactory factory = new JedisConnectionFactory(); | |
53 | + factory.setHostName(host); | |
54 | + factory.setPort(port); | |
55 | + factory.setDatabase(db); | |
56 | + factory.setPassword(password); | |
57 | + return factory; | |
58 | + } | |
59 | + | |
60 | + @Bean | |
61 | + public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) { | |
62 | + RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); | |
63 | + redisTemplate.setConnectionFactory(cf); | |
64 | + return redisTemplate; | |
65 | + } | |
66 | + | |
67 | + @Bean | |
68 | + public CacheManager cacheManager(RedisTemplate redisTemplate) { | |
69 | + return new RedisCacheManager(redisTemplate); | |
70 | + } | |
71 | + | |
72 | + @Bean | |
73 | + public KeyGenerator previousDeviceCredentialsId() { | |
74 | + return new PreviousDeviceCredentialsIdKeyGenerator(); | |
75 | + } | |
76 | + | |
77 | + | |
78 | +} | ... | ... |
... | ... | @@ -64,19 +64,28 @@ public class BaseRelationService implements RelationService { |
64 | 64 | return relationDao.checkRelation(from, to, relationType, typeGroup); |
65 | 65 | } |
66 | 66 | |
67 | - @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #to, #relationType}") | |
67 | + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #to, #relationType, #typeGroup}") | |
68 | 68 | @Override |
69 | - public ListenableFuture<EntityRelation> getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { | |
69 | + public EntityRelation getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { | |
70 | + try { | |
71 | + return getRelationAsync(from, to, relationType, typeGroup).get(); | |
72 | + } catch (InterruptedException | ExecutionException e) { | |
73 | + throw new RuntimeException(e); | |
74 | + } | |
75 | + } | |
76 | + | |
77 | + @Override | |
78 | + public ListenableFuture<EntityRelation> getRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { | |
70 | 79 | log.trace("Executing EntityRelation [{}][{}][{}][{}]", from, to, relationType, typeGroup); |
71 | 80 | validate(from, to, relationType, typeGroup); |
72 | 81 | return relationDao.getRelation(from, to, relationType, typeGroup); |
73 | 82 | } |
74 | 83 | |
75 | 84 | @Caching(evict = { |
76 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.from"), | |
77 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"), | |
78 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"), | |
79 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}") | |
85 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.typeGroup}"), | |
86 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type, #relation.typeGroup}"), | |
87 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.typeGroup}"), | |
88 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup}") | |
80 | 89 | }) |
81 | 90 | @Override |
82 | 91 | public boolean saveRelation(EntityRelation relation) { |
... | ... | @@ -86,10 +95,10 @@ public class BaseRelationService implements RelationService { |
86 | 95 | } |
87 | 96 | |
88 | 97 | @Caching(evict = { |
89 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.from"), | |
90 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"), | |
91 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"), | |
92 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}") | |
98 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.typeGroup}"), | |
99 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type, #relation.typeGroup}"), | |
100 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.typeGroup}"), | |
101 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup}") | |
93 | 102 | }) |
94 | 103 | @Override |
95 | 104 | public ListenableFuture<Boolean> saveRelationAsync(EntityRelation relation) { |
... | ... | @@ -99,11 +108,11 @@ public class BaseRelationService implements RelationService { |
99 | 108 | } |
100 | 109 | |
101 | 110 | @Caching(evict = { |
102 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.from"), | |
103 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"), | |
104 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"), | |
105 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}"), | |
106 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type}") | |
111 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.typeGroup}"), | |
112 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type, #relation.typeGroup}"), | |
113 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.typeGroup}"), | |
114 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup}"), | |
115 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type, #relation.typeGroup}") | |
107 | 116 | }) |
108 | 117 | @Override |
109 | 118 | public boolean deleteRelation(EntityRelation relation) { |
... | ... | @@ -117,7 +126,7 @@ public class BaseRelationService implements RelationService { |
117 | 126 | @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"), |
118 | 127 | @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"), |
119 | 128 | @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}"), |
120 | - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type}") | |
129 | + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type, #relation.typeGroup}") | |
121 | 130 | }) |
122 | 131 | @Override |
123 | 132 | public ListenableFuture<Boolean> deleteRelationAsync(EntityRelation relation) { |
... | ... | @@ -218,9 +227,9 @@ public class BaseRelationService implements RelationService { |
218 | 227 | ListenableFuture<List<List<EntityRelation>>> inboundRelationsTo = Futures.allAsList(inboundRelationsListTo); |
219 | 228 | ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelationsTo, |
220 | 229 | (AsyncFunction<List<List<EntityRelation>>, List<Boolean>>) relations -> { |
221 | - List<ListenableFuture<Boolean>> results = getListenableFutures(relations, cache, true); | |
222 | - return Futures.allAsList(results); | |
223 | - }); | |
230 | + List<ListenableFuture<Boolean>> results = getListenableFutures(relations, cache, true); | |
231 | + return Futures.allAsList(results); | |
232 | + }); | |
224 | 233 | |
225 | 234 | ListenableFuture<Boolean> inboundFuture = Futures.transform(inboundDeletions, getListToBooleanFunction()); |
226 | 235 | |
... | ... | @@ -272,9 +281,18 @@ public class BaseRelationService implements RelationService { |
272 | 281 | cache.evict(fromToAndType); |
273 | 282 | } |
274 | 283 | |
275 | - @Cacheable(cacheNames = RELATIONS_CACHE, key = "#from") | |
284 | + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #typeGroup}") | |
285 | + @Override | |
286 | + public List<EntityRelation> findByFrom(EntityId from, RelationTypeGroup typeGroup) { | |
287 | + try { | |
288 | + return findByFromAsync(from, typeGroup).get(); | |
289 | + } catch (InterruptedException | ExecutionException e) { | |
290 | + throw new RuntimeException(e); | |
291 | + } | |
292 | + } | |
293 | + | |
276 | 294 | @Override |
277 | - public ListenableFuture<List<EntityRelation>> findByFrom(EntityId from, RelationTypeGroup typeGroup) { | |
295 | + public ListenableFuture<List<EntityRelation>> findByFromAsync(EntityId from, RelationTypeGroup typeGroup) { | |
278 | 296 | log.trace("Executing findByFrom [{}][{}]", from, typeGroup); |
279 | 297 | validate(from); |
280 | 298 | validateTypeGroup(typeGroup); |
... | ... | @@ -300,9 +318,18 @@ public class BaseRelationService implements RelationService { |
300 | 318 | return relationsInfo; |
301 | 319 | } |
302 | 320 | |
303 | - @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #relationType}") | |
321 | + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #relationType, #typeGroup}") | |
322 | + @Override | |
323 | + public List<EntityRelation> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) { | |
324 | + try { | |
325 | + return findByFromAndTypeAsync(from, relationType, typeGroup).get(); | |
326 | + } catch (InterruptedException | ExecutionException e) { | |
327 | + throw new RuntimeException(e); | |
328 | + } | |
329 | + } | |
330 | + | |
304 | 331 | @Override |
305 | - public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) { | |
332 | + public ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(EntityId from, String relationType, RelationTypeGroup typeGroup) { | |
306 | 333 | log.trace("Executing findByFromAndType [{}][{}][{}]", from, relationType, typeGroup); |
307 | 334 | validate(from); |
308 | 335 | validateType(relationType); |
... | ... | @@ -310,9 +337,18 @@ public class BaseRelationService implements RelationService { |
310 | 337 | return relationDao.findAllByFromAndType(from, relationType, typeGroup); |
311 | 338 | } |
312 | 339 | |
313 | - @Cacheable(cacheNames = RELATIONS_CACHE, key = "#to") | |
340 | + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #typeGroup}") | |
341 | + @Override | |
342 | + public List<EntityRelation> findByTo(EntityId to, RelationTypeGroup typeGroup) { | |
343 | + try { | |
344 | + return findByToAsync(to, typeGroup).get(); | |
345 | + } catch (InterruptedException | ExecutionException e) { | |
346 | + throw new RuntimeException(e); | |
347 | + } | |
348 | + } | |
349 | + | |
314 | 350 | @Override |
315 | - public ListenableFuture<List<EntityRelation>> findByTo(EntityId to, RelationTypeGroup typeGroup) { | |
351 | + public ListenableFuture<List<EntityRelation>> findByToAsync(EntityId to, RelationTypeGroup typeGroup) { | |
316 | 352 | log.trace("Executing findByTo [{}][{}]", to, typeGroup); |
317 | 353 | validate(to); |
318 | 354 | validateTypeGroup(typeGroup); |
... | ... | @@ -351,9 +387,18 @@ public class BaseRelationService implements RelationService { |
351 | 387 | return entityRelationInfo; |
352 | 388 | } |
353 | 389 | |
354 | - @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #relationType}") | |
390 | + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #relationType, #typeGroup}") | |
391 | + @Override | |
392 | + public List<EntityRelation> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) { | |
393 | + try { | |
394 | + return findByToAndTypeAsync(to, relationType, typeGroup).get(); | |
395 | + } catch (InterruptedException | ExecutionException e) { | |
396 | + throw new RuntimeException(e); | |
397 | + } | |
398 | + } | |
399 | + | |
355 | 400 | @Override |
356 | - public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) { | |
401 | + public ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(EntityId to, String relationType, RelationTypeGroup typeGroup) { | |
357 | 402 | log.trace("Executing findByToAndType [{}][{}][{}]", to, relationType, typeGroup); |
358 | 403 | validate(to); |
359 | 404 | validateType(relationType); |
... | ... | @@ -527,9 +572,9 @@ public class BaseRelationService implements RelationService { |
527 | 572 | private ListenableFuture<List<EntityRelation>> findRelations(final EntityId rootId, final EntitySearchDirection direction) { |
528 | 573 | ListenableFuture<List<EntityRelation>> relations; |
529 | 574 | if (direction == EntitySearchDirection.FROM) { |
530 | - relations = findByFrom(rootId, RelationTypeGroup.COMMON); | |
575 | + relations = findByFromAsync(rootId, RelationTypeGroup.COMMON); | |
531 | 576 | } else { |
532 | - relations = findByTo(rootId, RelationTypeGroup.COMMON); | |
577 | + relations = findByToAsync(rootId, RelationTypeGroup.COMMON); | |
533 | 578 | } |
534 | 579 | return relations; |
535 | 580 | } | ... | ... |
... | ... | @@ -31,7 +31,9 @@ public interface RelationService { |
31 | 31 | |
32 | 32 | ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup); |
33 | 33 | |
34 | - ListenableFuture<EntityRelation> getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup); | |
34 | + EntityRelation getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup); | |
35 | + | |
36 | + ListenableFuture<EntityRelation> getRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup); | |
35 | 37 | |
36 | 38 | boolean saveRelation(EntityRelation relation); |
37 | 39 | |
... | ... | @@ -49,17 +51,25 @@ public interface RelationService { |
49 | 51 | |
50 | 52 | ListenableFuture<Boolean> deleteEntityRelationsAsync(EntityId entity); |
51 | 53 | |
52 | - ListenableFuture<List<EntityRelation>> findByFrom(EntityId from, RelationTypeGroup typeGroup); | |
54 | + List<EntityRelation> findByFrom(EntityId from, RelationTypeGroup typeGroup); | |
55 | + | |
56 | + ListenableFuture<List<EntityRelation>> findByFromAsync(EntityId from, RelationTypeGroup typeGroup); | |
53 | 57 | |
54 | 58 | ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from, RelationTypeGroup typeGroup); |
55 | 59 | |
56 | - ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup); | |
60 | + List<EntityRelation> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup); | |
61 | + | |
62 | + ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(EntityId from, String relationType, RelationTypeGroup typeGroup); | |
57 | 63 | |
58 | - ListenableFuture<List<EntityRelation>> findByTo(EntityId to, RelationTypeGroup typeGroup); | |
64 | + List<EntityRelation> findByTo(EntityId to, RelationTypeGroup typeGroup); | |
65 | + | |
66 | + ListenableFuture<List<EntityRelation>> findByToAsync(EntityId to, RelationTypeGroup typeGroup); | |
59 | 67 | |
60 | 68 | ListenableFuture<List<EntityRelationInfo>> findInfoByTo(EntityId to, RelationTypeGroup typeGroup); |
61 | 69 | |
62 | - ListenableFuture<List<EntityRelation>> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup); | |
70 | + List<EntityRelation> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup); | |
71 | + | |
72 | + ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(EntityId to, String relationType, RelationTypeGroup typeGroup); | |
63 | 73 | |
64 | 74 | ListenableFuture<List<EntityRelation>> findByQuery(EntityRelationsQuery query); |
65 | 75 | ... | ... |
... | ... | @@ -122,7 +122,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest { |
122 | 122 | saveRelation(relationB1); |
123 | 123 | saveRelation(relationB2); |
124 | 124 | |
125 | - List<EntityRelation> relations = relationService.findByFrom(parentA, RelationTypeGroup.COMMON).get(); | |
125 | + List<EntityRelation> relations = relationService.findByFrom(parentA, RelationTypeGroup.COMMON); | |
126 | 126 | Assert.assertEquals(2, relations.size()); |
127 | 127 | for (EntityRelation relation : relations) { |
128 | 128 | Assert.assertEquals(EntityRelation.CONTAINS_TYPE, relation.getType()); |
... | ... | @@ -130,13 +130,13 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest { |
130 | 130 | Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo())); |
131 | 131 | } |
132 | 132 | |
133 | - relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); | |
133 | + relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON); | |
134 | 134 | Assert.assertEquals(2, relations.size()); |
135 | 135 | |
136 | - relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); | |
136 | + relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON); | |
137 | 137 | Assert.assertEquals(0, relations.size()); |
138 | 138 | |
139 | - relations = relationService.findByFrom(parentB, RelationTypeGroup.COMMON).get(); | |
139 | + relations = relationService.findByFrom(parentB, RelationTypeGroup.COMMON); | |
140 | 140 | Assert.assertEquals(2, relations.size()); |
141 | 141 | for (EntityRelation relation : relations) { |
142 | 142 | Assert.assertEquals(EntityRelation.MANAGES_TYPE, relation.getType()); |
... | ... | @@ -144,10 +144,10 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest { |
144 | 144 | Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo())); |
145 | 145 | } |
146 | 146 | |
147 | - relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); | |
147 | + relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON); | |
148 | 148 | Assert.assertEquals(0, relations.size()); |
149 | 149 | |
150 | - relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); | |
150 | + relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON); | |
151 | 151 | Assert.assertEquals(0, relations.size()); |
152 | 152 | } |
153 | 153 | |
... | ... | @@ -177,26 +177,26 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest { |
177 | 177 | // Data propagation to views is async |
178 | 178 | Thread.sleep(3000); |
179 | 179 | |
180 | - List<EntityRelation> relations = relationService.findByTo(childA, RelationTypeGroup.COMMON).get(); | |
180 | + List<EntityRelation> relations = relationService.findByTo(childA, RelationTypeGroup.COMMON); | |
181 | 181 | Assert.assertEquals(2, relations.size()); |
182 | 182 | for (EntityRelation relation : relations) { |
183 | 183 | Assert.assertEquals(childA, relation.getTo()); |
184 | 184 | Assert.assertTrue(parentA.equals(relation.getFrom()) || parentB.equals(relation.getFrom())); |
185 | 185 | } |
186 | 186 | |
187 | - relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get(); | |
187 | + relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON); | |
188 | 188 | Assert.assertEquals(1, relations.size()); |
189 | 189 | |
190 | - relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); | |
190 | + relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON); | |
191 | 191 | Assert.assertEquals(1, relations.size()); |
192 | 192 | |
193 | - relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); | |
193 | + relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON); | |
194 | 194 | Assert.assertEquals(0, relations.size()); |
195 | 195 | |
196 | - relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get(); | |
196 | + relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON); | |
197 | 197 | Assert.assertEquals(0, relations.size()); |
198 | 198 | |
199 | - relations = relationService.findByTo(childB, RelationTypeGroup.COMMON).get(); | |
199 | + relations = relationService.findByTo(childB, RelationTypeGroup.COMMON); | |
200 | 200 | Assert.assertEquals(2, relations.size()); |
201 | 201 | for (EntityRelation relation : relations) { |
202 | 202 | Assert.assertEquals(childB, relation.getTo()); | ... | ... |
1 | -cache.enabled=false | |
2 | -cache.device_credentials.time_to_live=3600 | |
3 | -cache.device_credentials.max_size.size=1000000 | |
4 | -cache.device_credentials.max_size.policy=PER_NODE | |
5 | - | |
6 | 1 | zk.enabled=false |
7 | 2 | zk.url=localhost:2181 |
8 | 3 | zk.zk_dir=/thingsboard |
9 | 4 | |
10 | 5 | updates.enabled=false |
11 | 6 | |
12 | -caching.specs.relations.timeToLiveInMinutes=1440 | |
13 | -caching.specs.relations.maxSize=100000 | |
7 | +cache.type=caffeine | |
8 | +#cache.type=redis | |
9 | + | |
10 | +caffeine.specs.relations.timeToLiveInMinutes=1440 | |
11 | +caffeine.specs.relations.maxSize=100000 | |
12 | + | |
13 | +caffeine.specs.deviceCredentials.timeToLiveInMinutes=1440 | |
14 | +caffeine.specs.deviceCredentials.maxSize=100000 | |
14 | 15 | |
15 | -caching.specs.deviceCredentials.timeToLiveInMinutes=1440 | |
16 | -caching.specs.deviceCredentials.maxSize=100000 | |
16 | +caffeine.specs.devices.timeToLiveInMinutes=1440 | |
17 | +caffeine.specs.devices.maxSize=100000 | |
17 | 18 | |
18 | -caching.specs.devices.timeToLiveInMinutes=1440 | |
19 | -caching.specs.devices.maxSize=100000 | |
\ No newline at end of file | ||
19 | +redis.connection.host=localhost | |
20 | +redis.connection.port=6379 | |
21 | +redis.connection.db=0 | |
22 | +redis.connection.password= | |
\ No newline at end of file | ... | ... |
docker/docker-compose-tests.yml
0 → 100644
1 | +# | |
2 | +# Copyright © 2016-2017 The Thingsboard Authors | |
3 | +# | |
4 | +# Licensed under the Apache License, Version 2.0 (the "License"); | |
5 | +# you may not use this file except in compliance with the License. | |
6 | +# You may obtain a copy of the License at | |
7 | +# | |
8 | +# http://www.apache.org/licenses/LICENSE-2.0 | |
9 | +# | |
10 | +# Unless required by applicable law or agreed to in writing, software | |
11 | +# distributed under the License is distributed on an "AS IS" BASIS, | |
12 | +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | +# See the License for the specific language governing permissions and | |
14 | +# limitations under the License. | |
15 | +# | |
16 | + | |
17 | +version: '3.3' | |
18 | +services: | |
19 | + redis: | |
20 | + image: redis:4.0 | |
21 | + networks: | |
22 | + - core | |
23 | + ports: | |
24 | + - "6379:6379" | |
25 | + | |
26 | +networks: | |
27 | + core: | ... | ... |
... | ... | @@ -32,6 +32,8 @@ |
32 | 32 | <spring-boot.version>1.4.3.RELEASE</spring-boot.version> |
33 | 33 | <spring.version>4.3.4.RELEASE</spring.version> |
34 | 34 | <spring-security.version>4.2.0.RELEASE</spring-security.version> |
35 | + <spring-data-redis.version>1.8.10.RELEASE</spring-data-redis.version> | |
36 | + <jedis.version>2.9.0</jedis.version> | |
35 | 37 | <jjwt.version>0.7.0</jjwt.version> |
36 | 38 | <json-path.version>2.2.0</json-path.version> |
37 | 39 | <junit.version>4.12</junit.version> |
... | ... | @@ -784,6 +786,16 @@ |
784 | 786 | <scope>test</scope> |
785 | 787 | </dependency> |
786 | 788 | <dependency> |
789 | + <groupId>org.springframework.data</groupId> | |
790 | + <artifactId>spring-data-redis</artifactId> | |
791 | + <version>${spring-data-redis.version}</version> | |
792 | + </dependency> | |
793 | + <dependency> | |
794 | + <groupId>redis.clients</groupId> | |
795 | + <artifactId>jedis</artifactId> | |
796 | + <version>${jedis.version}</version> | |
797 | + </dependency> | |
798 | + <dependency> | |
787 | 799 | <groupId>com.sun.winsw</groupId> |
788 | 800 | <artifactId>winsw</artifactId> |
789 | 801 | <version>${winsw.version}</version> | ... | ... |