diff --git a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedback.java b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedback.java
index 354fc41c50..5478ad1ed2 100644
--- a/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedback.java
+++ b/hawkbit-ddi/hawkbit-ddi-api/src/main/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedback.java
@@ -31,7 +31,7 @@
*
*
* The answer header would look like: {
- * "time": "20140511T121314",
+ * "timestamp": "1733218554123",
* "status": {
* "execution": "closed",
* "result": {
@@ -47,8 +47,8 @@
@JsonIgnoreProperties(ignoreUnknown = true)
public class DdiActionFeedback {
- @Schema(description = "Timestamp of the action", example = "2023-08-03T12:31:41.890992967Z")
- private final String time;
+ @Schema(description = "Timestamp of the action in milliseconds since epoch", example = "1627997501890")
+ private final Long timestamp;
@NotNull
@Valid
@@ -57,14 +57,19 @@ public class DdiActionFeedback {
/**
* Constructs an action-feedback
*
- * @param time time of feedback
+ * @param timestamp time of feedback
* @param status status to be appended to the action
*/
@JsonCreator
public DdiActionFeedback(
- @JsonProperty(value = "time") final String time,
- @JsonProperty(value = "status", required = true) final DdiStatus status) {
- this.time = time;
+ @JsonProperty(value = "status", required = true) final DdiStatus status,
+ @JsonProperty(value = "timestamp") final Long timestamp) {
this.status = status;
+ this.timestamp = timestamp != null ? timestamp : System.currentTimeMillis();
}
+
+ public DdiActionFeedback(final DdiStatus status) {
+ this(status, null);
+ }
+
}
\ No newline at end of file
diff --git a/hawkbit-ddi/hawkbit-ddi-api/src/test/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedbackTest.java b/hawkbit-ddi/hawkbit-ddi-api/src/test/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedbackTest.java
index 395f42d418..a0520a5793 100644
--- a/hawkbit-ddi/hawkbit-ddi-api/src/test/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedbackTest.java
+++ b/hawkbit-ddi/hawkbit-ddi-api/src/test/java/org/eclipse/hawkbit/ddi/json/model/DdiActionFeedbackTest.java
@@ -39,7 +39,7 @@ class DdiActionFeedbackTest {
void shouldSerializeAndDeserializeObjectWithoutOptionalValues() throws IOException {
// Setup
final DdiStatus ddiStatus = new DdiStatus(DdiStatus.ExecutionStatus.CLOSED, null, null, Collections.emptyList());
- final DdiActionFeedback ddiActionFeedback = new DdiActionFeedback(null, ddiStatus);
+ final DdiActionFeedback ddiActionFeedback = new DdiActionFeedback(ddiStatus);
// Test
final String serializedDdiActionFeedback = mapper.writeValueAsString(ddiActionFeedback);
@@ -53,17 +53,16 @@ void shouldSerializeAndDeserializeObjectWithoutOptionalValues() throws IOExcepti
@Description("Verify the correct serialization and deserialization of the model with all values provided")
void shouldSerializeAndDeserializeObjectWithOptionalValues() throws IOException {
// Setup
- final String time = Instant.now().toString();
+ final Long timestamp = System.currentTimeMillis();
final DdiResult ddiResult = new DdiResult(DdiResult.FinalResult.SUCCESS, new DdiProgress(10, 10));
final DdiStatus ddiStatus = new DdiStatus(DdiStatus.ExecutionStatus.CLOSED, ddiResult, 200, Collections.singletonList("myMessage"));
- final DdiActionFeedback ddiActionFeedback = new DdiActionFeedback(time, ddiStatus);
+ final DdiActionFeedback ddiActionFeedback = new DdiActionFeedback(ddiStatus, timestamp);
// Test
final String serializedDdiActionFeedback = mapper.writeValueAsString(ddiActionFeedback);
final DdiActionFeedback deserializedDdiActionFeedback = mapper.readValue(serializedDdiActionFeedback, DdiActionFeedback.class);
- assertThat(serializedDdiActionFeedback).contains(time);
- assertThat(deserializedDdiActionFeedback.getTime()).isEqualTo(time);
+ assertThat(deserializedDdiActionFeedback.getTimestamp()).isEqualTo(timestamp);
assertThat(deserializedDdiActionFeedback.getStatus()).hasToString(ddiStatus.toString());
}
@@ -71,28 +70,38 @@ void shouldSerializeAndDeserializeObjectWithOptionalValues() throws IOException
@Description("Verify that deserialization fails for known properties with a wrong datatype")
void shouldFailForObjectWithWrongDataTypes() throws IOException {
// Setup
- final String serializedDdiActionFeedback = "{\"time\":\"20190809T121314\",\"status\":{\"execution\": [closed],\"result\":null,\"details\":[]}}";
-
+ final String serializedDdiActionFeedback = """
+ {
+ "timestamp" : "1627997501890",
+ "status" : {
+ "execution" : "[closed]",
+ "result" : null,
+ "details" : []
+ }
+ }
+ """;
assertThatExceptionOfType(MismatchedInputException.class).isThrownBy(
() -> mapper.readValue(serializedDdiActionFeedback, DdiActionFeedback.class));
}
@Test
@Description("Verify that deserialization works if optional fields are not parsed")
- void shouldConvertItWithoutOptionalFieldTime() throws JsonProcessingException {
+ void shouldConvertItWithoutOptionalFieldTimestamp() throws JsonProcessingException {
// Setup
- final String serializedDdiActionFeedback = "{\n" + //
- " \"status\" : {\n" + //
- " \"result\" : {\n" + //
- " \"finished\" : \"none\"\n" + //
- " },\n" + //
- " \"execution\" : \"download\",\n" + //
- " \"details\" : [ \"Some message\" ]\n" + //
- " }\n" + //
- "}";//
+ final String serializedDdiActionFeedback = """
+ {
+ "status" : {
+ "result" : {
+ "finished" : "none"
+ },
+ "execution" : "download",
+ "details" : [ "Some message" ]
+ }
+ }
+ """;
assertThat(mapper.readValue(serializedDdiActionFeedback, DdiActionFeedback.class)).satisfies(deserializedDdiActionFeedback -> {
- assertThat(deserializedDdiActionFeedback.getTime()).isNull();
+ assertThat(deserializedDdiActionFeedback.getTimestamp()).isNotNull();
assertThat(deserializedDdiActionFeedback.getStatus()).isNotNull();
assertThat(deserializedDdiActionFeedback.getStatus().getResult()).isNotNull();
assertThat(deserializedDdiActionFeedback.getStatus().getResult().getFinished()).isEqualTo(DdiResult.FinalResult.NONE);
diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java
index 0149e5b046..9fd779ff6f 100644
--- a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java
+++ b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java
@@ -503,7 +503,7 @@ private static void addMessageIfEmpty(final String text, final List mess
private static ActionStatusCreate generateActionCancelStatus(
final DdiActionFeedback feedback, final Target target, final Long actionId, final EntityFactory entityFactory) {
- final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId);
+ final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId).occurredAt(feedback.getTimestamp());
final List messages = new ArrayList<>();
final Status status;
switch (feedback.getStatus().getExecution()) {
@@ -616,7 +616,7 @@ private ActionStatus checkAndLogDownload(final HttpServletRequest request, final
}
private ActionStatusCreate generateUpdateStatus(final DdiActionFeedback feedback, final String controllerId, final Long actionId) {
- final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId);
+ final ActionStatusCreate actionStatusCreate = entityFactory.actionStatus().create(actionId).occurredAt(feedback.getTimestamp());
final List messages = new ArrayList<>();
if (!CollectionUtils.isEmpty(feedback.getStatus().getDetails())) {
diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java
index 0af6cc31ec..31042fe266 100644
--- a/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java
+++ b/hawkbit-ddi/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/AbstractDDiApiIntegrationTest.java
@@ -295,7 +295,7 @@ protected String getJsonActionFeedback(
final DdiStatus.ExecutionStatus executionStatus, final DdiResult ddiResult,
final List messages) throws JsonProcessingException {
final DdiStatus ddiStatus = new DdiStatus(executionStatus, ddiResult, null, messages);
- return OBJECT_MAPPER.writeValueAsString(new DdiActionFeedback(Instant.now().toString(), ddiStatus));
+ return OBJECT_MAPPER.writeValueAsString(new DdiActionFeedback(ddiStatus));
}
protected String getJsonActionFeedback(
@@ -308,7 +308,7 @@ protected String getJsonActionFeedback(
final DdiStatus.ExecutionStatus executionStatus,
final DdiResult.FinalResult finalResult, final Integer code, final List messages) throws JsonProcessingException {
final DdiStatus ddiStatus = new DdiStatus(executionStatus, new DdiResult(finalResult, new DdiProgress(2, 5)), code, messages);
- return OBJECT_MAPPER.writeValueAsString(new DdiActionFeedback(Instant.now().toString(), ddiStatus));
+ return OBJECT_MAPPER.writeValueAsString(new DdiActionFeedback(ddiStatus));
}
protected String getJsonConfirmationFeedback(
diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AbstractAmqpServiceIntegrationTest.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AbstractAmqpServiceIntegrationTest.java
index 9aaa342342..2f5f050713 100644
--- a/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AbstractAmqpServiceIntegrationTest.java
+++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/test/java/org/eclipse/hawkbit/integration/AbstractAmqpServiceIntegrationTest.java
@@ -330,7 +330,7 @@ protected Message createPingMessage(final String correlationId, final String ten
protected void createAndSendActionStatusUpdateMessage(final String target, final long actionId,
final DmfActionStatus status) {
- final DmfActionUpdateStatus dmfActionUpdateStatus = new DmfActionUpdateStatus(actionId, status);
+ final DmfActionUpdateStatus dmfActionUpdateStatus = new DmfActionUpdateStatus(actionId, status, System.currentTimeMillis());
final Message eventMessage = createUpdateActionEventMessage(dmfActionUpdateStatus);
eventMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.THING_ID, target);
diff --git a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfActionUpdateStatus.java b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfActionUpdateStatus.java
index 16df9ded85..f6edba82b3 100644
--- a/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfActionUpdateStatus.java
+++ b/hawkbit-dmf/hawkbit-dmf-api/src/main/java/org/eclipse/hawkbit/dmf/json/model/DmfActionUpdateStatus.java
@@ -34,6 +34,7 @@ public class DmfActionUpdateStatus {
private final Long actionId;
private final DmfActionStatus actionStatus;
+ private final long timestamp;
@JsonProperty
private Long softwareModuleId;
@@ -46,9 +47,14 @@ public class DmfActionUpdateStatus {
private Integer code;
public DmfActionUpdateStatus(@JsonProperty(value = "actionId", required = true) final Long actionId,
- @JsonProperty(value = "actionStatus", required = true) final DmfActionStatus actionStatus) {
+ @JsonProperty(value = "actionStatus", required = true) final DmfActionStatus actionStatus, @JsonProperty(value = "timestamp") final Long timestamp) {
this.actionId = actionId;
this.actionStatus = actionStatus;
+ this.timestamp = timestamp != null ? timestamp : System.currentTimeMillis();
+ }
+
+ public DmfActionUpdateStatus(final Long actionId, final DmfActionStatus actionStatus) {
+ this(actionId, actionStatus, null);
}
@JsonIgnore
diff --git a/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtAction.java b/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtAction.java
index ab1091e56f..64b16e81f3 100644
--- a/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtAction.java
+++ b/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtAction.java
@@ -131,4 +131,5 @@ public class MgmtAction extends MgmtBaseEntity {
@JsonProperty
@Schema(description = "If created by external system this field contains the external reference for the action")
private String externalRef;
+
}
\ No newline at end of file
diff --git a/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java b/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java
index e043964de6..785df0e740 100644
--- a/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java
+++ b/hawkbit-mgmt/hawkbit-mgmt-api/src/main/java/org/eclipse/hawkbit/mgmt/json/model/action/MgmtActionStatus.java
@@ -43,6 +43,10 @@ public class MgmtActionStatus {
@Schema(example = "1691065929524")
private Long reportedAt;
+ @JsonProperty
+ @Schema(example = "1691065929524")
+ private Long timestamp;
+
@JsonProperty
@Schema(example = "200")
private Integer code;
diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java
index c50e42bf72..0a322a1a40 100644
--- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java
+++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTargetMapper.java
@@ -354,6 +354,7 @@ private static MgmtActionStatus toResponse(final ActionStatus actionStatus, fina
result.setMessages(messages);
result.setReportedAt(actionStatus.getCreatedAt());
+ result.setTimestamp(actionStatus.getOccurredAt());
result.setStatusId(actionStatus.getId());
result.setType(actionStatus.getStatus().name().toLowerCase());
actionStatus.getCode().ifPresent(result::setCode);
diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/TimestampCalculator.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/TimestampCalculator.java
index e2bc7932ef..be205439f0 100644
--- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/TimestampCalculator.java
+++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/TimestampCalculator.java
@@ -37,7 +37,7 @@ public final class TimestampCalculator {
* @return overdue_ts in milliseconds since Unix epoch as long value
*/
public static long calculateOverdueTimestamp() {
- return Instant.now().toEpochMilli() - getDurationForKey(TenantConfigurationKey.POLLING_TIME_INTERVAL).toMillis()
+ return System.currentTimeMillis() - getDurationForKey(TenantConfigurationKey.POLLING_TIME_INTERVAL).toMillis()
- getDurationForKey(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL).toMillis();
}
diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyResolver.java b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyResolver.java
index 1842841849..1d99864ea0 100644
--- a/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyResolver.java
+++ b/hawkbit-repository/hawkbit-repository-core/src/main/java/org/eclipse/hawkbit/repository/rsql/VirtualPropertyResolver.java
@@ -10,7 +10,6 @@
package org.eclipse.hawkbit.repository.rsql;
import java.io.Serial;
-import java.time.Instant;
import org.apache.commons.lang3.text.StrLookup;
import org.apache.commons.lang3.text.StrSubstitutor;
@@ -54,7 +53,7 @@ public String lookup(final String rhs) {
String resolved = null;
if ("now_ts".equalsIgnoreCase(rhs)) {
- resolved = String.valueOf(Instant.now().toEpochMilli());
+ resolved = String.valueOf(System.currentTimeMillis());
} else if ("overdue_ts".equalsIgnoreCase(rhs)) {
resolved = String.valueOf(TimestampCalculator.calculateOverdueTimestamp());
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java
index c2b274155d..e79132e54b 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaActionManagement.java
@@ -88,7 +88,7 @@ protected JpaAction getActionAndThrowExceptionIfNotFound(final Long actionId) {
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
}
- protected void onActionStatusUpdate(final Action.Status updatedActionStatus, final JpaAction action) {
+ protected void onActionStatusUpdate(final JpaActionStatus newActionStatus, final JpaAction action) {
// can be overwritten to intercept the persistence of the action status
}
@@ -165,7 +165,7 @@ private Action handleAddUpdateActionStatus(final JpaActionStatus actionStatus, f
assertActionStatusMessageQuota(actionStatus);
actionStatus.setAction(action);
- onActionStatusUpdate(actionStatus.getStatus(), action);
+ onActionStatusUpdate(actionStatus, action);
actionStatusRepository.save(actionStatus);
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java
index 4c7a306af7..a7ae954877 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaConfirmationManagement.java
@@ -163,8 +163,8 @@ public void deactivateAutoConfirmation(String controllerId) {
}
@Override
- protected void onActionStatusUpdate(final Status updatedActionStatus, final JpaAction action) {
- if (updatedActionStatus == Status.RUNNING && action.isActive()) {
+ protected void onActionStatusUpdate(final JpaActionStatus newActionStatus, final JpaAction action) {
+ if (newActionStatus.getStatus() == Status.RUNNING && action.isActive()) {
action.setStatus(Status.RUNNING);
}
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java
index a8283f3f9f..a6187b609b 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java
@@ -177,7 +177,9 @@ public int getWeightConsideringDefault(final Action action) {
}
@Override
- protected void onActionStatusUpdate(final Action.Status updatedActionStatus, final JpaAction action) {
+ protected void onActionStatusUpdate(final JpaActionStatus newActionStatus, final JpaAction action) {
+ final Action.Status updatedActionStatus = newActionStatus.getStatus();
+ final long occurredAt = newActionStatus.getOccurredAt();
switch (updatedActionStatus) {
case ERROR: {
final JpaTarget target = (JpaTarget) action.getTarget();
@@ -186,7 +188,7 @@ protected void onActionStatusUpdate(final Action.Status updatedActionStatus, fin
break;
}
case FINISHED: {
- handleFinishedAndStoreInTargetStatus(action).ifPresent(this::requestControllerAttributes);
+ handleFinishedAndStoreInTargetStatus(occurredAt, action).ifPresent(this::requestControllerAttributes);
break;
}
case DOWNLOADED: {
@@ -865,33 +867,35 @@ private void handleErrorOnAction(final JpaAction mergedAction, final JpaTarget m
* @return a present controllerId in case the attributes needs to be
* requested.
*/
- private Optional handleFinishedAndStoreInTargetStatus(final JpaAction action) {
+ private Optional handleFinishedAndStoreInTargetStatus(final long occurredAt, final JpaAction action) {
final JpaTarget target = (JpaTarget) action.getTarget();
action.setActive(false);
action.setStatus(Status.FINISHED);
- final JpaDistributionSet ds = (JpaDistributionSet) entityManager.merge(action.getDistributionSet());
-
- target.setInstalledDistributionSet(ds);
- target.setInstallationDate(System.currentTimeMillis());
+ if (target.getInstallationDate() == null || target.getInstallationDate() < occurredAt) {
+ final JpaDistributionSet ds = (JpaDistributionSet) entityManager.merge(action.getDistributionSet());
+
+ target.setInstalledDistributionSet(ds);
+ target.setInstallationDate(occurredAt);
+
+ // Target reported an installation of a DOWNLOAD_ONLY assignment, the
+ // assigned DS has to be adapted
+ // because the currently assigned DS can be unequal to the currently
+ // installed DS (the downloadOnly DS)
+ if (isDownloadOnly(action)) {
+ target.setAssignedDistributionSet((JpaDistributionSet) action.getDistributionSet());
+ }
- // Target reported an installation of a DOWNLOAD_ONLY assignment, the
- // assigned DS has to be adapted
- // because the currently assigned DS can be unequal to the currently
- // installed DS (the downloadOnly DS)
- if (isDownloadOnly(action)) {
- target.setAssignedDistributionSet((JpaDistributionSet) action.getDistributionSet());
- }
+ // check if the assigned set is equal to the installed set (not
+ // necessarily the case as another update might be pending already).
+ if (target.getAssignedDistributionSet() != null
+ && target.getAssignedDistributionSet().getId().equals(target.getInstalledDistributionSet().getId())) {
+ target.setUpdateStatus(TargetUpdateStatus.IN_SYNC);
+ }
- // check if the assigned set is equal to the installed set (not
- // necessarily the case as another update might be pending already).
- if (target.getAssignedDistributionSet() != null
- && target.getAssignedDistributionSet().getId().equals(target.getInstalledDistributionSet().getId())) {
- target.setUpdateStatus(TargetUpdateStatus.IN_SYNC);
+ targetRepository.save(target);
+ entityManager.detach(ds);
}
- targetRepository.save(target);
- entityManager.detach(ds);
-
return Optional.of(target.getControllerId());
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java
index 27f1a83d44..87f59e9ec5 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaAction.java
@@ -18,6 +18,8 @@
import java.util.Map;
import java.util.Optional;
+import jakarta.persistence.Access;
+import jakarta.persistence.AccessType;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.ConstraintMode;
@@ -51,6 +53,7 @@
import org.eclipse.hawkbit.repository.model.RolloutGroup;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
+import org.springframework.data.annotation.CreatedDate;
/**
* JPA implementation of {@link Action}.
@@ -283,6 +286,7 @@ public Optional getLastActionStatusCode() {
return Optional.ofNullable(lastActionStatusCode);
}
+
@Override
public Optional getMaintenanceWindowStartTime() {
return MaintenanceScheduleHelper.getNextMaintenanceWindow(maintenanceWindowSchedule, maintenanceWindowDuration,
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java
index 789d5e5ee8..fd0a93aaa3 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementSearchTest.java
@@ -89,7 +89,7 @@ void targetSearchWithVariousFilterCombinations() {
final DistributionSet installedSet = testdataFactory.createDistributionSet("another");
- final Long lastTargetQueryNotOverdue = Instant.now().toEpochMilli();
+ final Long lastTargetQueryNotOverdue = System.currentTimeMillis();
final Long lastTargetQueryAlwaysOverdue = 0L;
final String targetDsAIdPref = "targ-A";
@@ -276,7 +276,7 @@ void targetSearchWithOrderByDistributionSetAndSortParam() {
void targetSearchWithOverdueFilterAndOrderByDistributionSet() {
final Long lastTargetQueryAlwaysOverdue = 0L;
- final long lastTargetQueryNotOverdue = Instant.now().toEpochMilli();
+ final long lastTargetQueryNotOverdue = System.currentTimeMillis();
final Long[] overdueMix = { lastTargetQueryAlwaysOverdue, lastTargetQueryNotOverdue,
lastTargetQueryAlwaysOverdue, null, lastTargetQueryAlwaysOverdue };
diff --git a/hawkbit-sdk/hawkbit-sdk-device/src/main/java/org/eclipse/hawkbit/sdk/device/UpdateStatus.java b/hawkbit-sdk/hawkbit-sdk-device/src/main/java/org/eclipse/hawkbit/sdk/device/UpdateStatus.java
index 214427bc56..f5953a1a62 100644
--- a/hawkbit-sdk/hawkbit-sdk-device/src/main/java/org/eclipse/hawkbit/sdk/device/UpdateStatus.java
+++ b/hawkbit-sdk/hawkbit-sdk-device/src/main/java/org/eclipse/hawkbit/sdk/device/UpdateStatus.java
@@ -18,8 +18,7 @@
public record UpdateStatus(Status status, List messages) {
DdiActionFeedback feedback() {
- return new DdiActionFeedback(null,
- new DdiStatus(status.executionStatus, new DdiResult(status.finalResult, null), status.code, messages));
+ return new DdiActionFeedback(new DdiStatus(status.executionStatus, new DdiResult(status.finalResult, null), status.code, messages));
}
/**