-
Notifications
You must be signed in to change notification settings - Fork 61
fix: discard update action on notify only #1637
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,7 +52,6 @@ public class UpdateSystemPolicyService extends GreengrassService { | |
| // represents the value in seconds the kernel will wait for components to respond to | ||
| // an precomponent update event | ||
| private final Map<String, UpdateAction> pendingActions = Collections.synchronizedMap(new LinkedHashMap<>()); | ||
| private final AtomicReference<String> actionInProgress = new AtomicReference<>(); | ||
|
|
||
| @Inject | ||
| private LifecycleIPCEventStreamAgent lifecycleIPCAgent; | ||
|
|
@@ -96,20 +95,21 @@ public Set<String> getPendingActions() { | |
| @SuppressWarnings("PMD.AvoidCatchingThrowable") | ||
| protected void runUpdateActions(String deploymentId) { | ||
| try (LockScope ls = LockScope.lock(lock)) { | ||
| for (Map.Entry<String, UpdateAction> todo : pendingActions.entrySet()) { | ||
| try { | ||
| actionInProgress.set(todo.getKey()); | ||
| todo.getValue().getAction().run(); | ||
| logger.atDebug().setEventType("service-update-action").addKeyValue("action", todo.getKey()).log(); | ||
| } catch (Throwable t) { | ||
| logger.atError().setEventType("service-update-action-error").addKeyValue("action", todo.getKey()) | ||
| .setCause(t).log(); | ||
| } | ||
| final UpdateAction pendingUpdateAction = pendingActions.remove(deploymentId); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix: Pending actions that only correspond to the specified deployment id should be performed.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean that a deferred deployment cannot be cancelled? Ideally, if a component is deferring a config merge due a deployment, this deployment should still be cancellable given that defer period is still ongoing.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| if (pendingUpdateAction == null) { | ||
| // Update action is never added or discarded by this time. So, do nothing. | ||
| return; | ||
| } | ||
| try { | ||
| pendingUpdateAction.getAction().run(); | ||
| logger.atDebug().setEventType("service-update-action").addKeyValue("action", deploymentId).log(); | ||
| } catch (Throwable t) { | ||
| logger.atError().setEventType("service-update-action-error").addKeyValue("action", deploymentId) | ||
| .setCause(t).log(); | ||
| } | ||
| pendingActions.clear(); | ||
| lifecycleIPCAgent.sendPostComponentUpdateEvent( | ||
| new PostComponentUpdateEvent().withDeploymentId(deploymentId)); | ||
| actionInProgress.set(null); | ||
|
|
||
| } | ||
| } | ||
|
|
||
|
|
@@ -121,16 +121,13 @@ protected void runUpdateActions(String deploymentId) { | |
| * false if update actions were already in progress | ||
| */ | ||
| public boolean discardPendingUpdateAction(String tag) { | ||
| if (tag.equals(actionInProgress.get())) { | ||
| final UpdateAction pendingUpdateAction = pendingActions.remove(tag); | ||
| if (pendingUpdateAction == null) { | ||
| // Update action is never added or already in progress. | ||
| return false; | ||
| } | ||
| final UpdateAction pendingUpdateAction = pendingActions.get(tag); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix - race: A thread can reach this point before the update action is completed (but in progress) resulting in returning an incorrect value for Use |
||
| if (pendingUpdateAction != null) { | ||
| // Signal components that they can resume their work since the update is not going to happen | ||
| lifecycleIPCAgent.sendPostComponentUpdateEvent( | ||
| new PostComponentUpdateEvent().withDeploymentId(pendingUpdateAction.getDeploymentId())); | ||
| pendingActions.remove(tag); | ||
| } | ||
| // Signal components that they can resume their work since the update is not going to happen | ||
| lifecycleIPCAgent.sendPostComponentUpdateEvent(new PostComponentUpdateEvent().withDeploymentId(tag)); | ||
| return true; | ||
| } | ||
|
|
||
|
|
@@ -150,18 +147,17 @@ protected void startup() throws InterruptedException { | |
| logger.atDebug().setEventType("service-update-pending").addKeyValue("numOfUpdates", pendingActions.size()) | ||
| .log(); | ||
|
|
||
| boolean ggcRestarting = false; | ||
| for (UpdateAction action : pendingActions.values()) { | ||
| if (action.isGgcRestart()) { | ||
| ggcRestarting = true; | ||
| break; | ||
| } | ||
| final AtomicReference<UpdateAction> action = new AtomicReference<>(); | ||
| pendingActions.values().stream().findFirst().ifPresent(action::set); | ||
| if (action.get() == null) { | ||
| // no pending actions | ||
| continue; | ||
| } | ||
| String deploymentId = action.get().getDeploymentId(); | ||
| PreComponentUpdateEvent preComponentUpdateEvent = new PreComponentUpdateEvent() | ||
| .withDeploymentId(deploymentId) | ||
| .withIsGgcRestarting(action.get().isGgcRestart()); | ||
|
|
||
| PreComponentUpdateEvent preComponentUpdateEvent = new PreComponentUpdateEvent(); | ||
| preComponentUpdateEvent.setIsGgcRestarting(ggcRestarting); | ||
| String deploymentId = pendingActions.values().stream().map(UpdateAction::getDeploymentId).findFirst().get(); | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix: At this point, |
||
| preComponentUpdateEvent.setDeploymentId(deploymentId); | ||
| List<Future<DeferComponentUpdateRequest>> deferRequestFutures = | ||
| lifecycleIPCAgent.sendPreComponentUpdateEvent(preComponentUpdateEvent); | ||
|
|
||
|
|
@@ -179,8 +175,7 @@ protected void startup() throws InterruptedException { | |
| logger.atInfo().setEventType("service-update-finish").log(); | ||
| }).get(); | ||
| } catch (ExecutionException e) { | ||
| logger.atError().setEventType("service-update-error") | ||
| .log("Run update actions errored", e); | ||
| logger.atError().setEventType("service-update-error").log("Run update actions errored", e); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| { | ||
| "deploymentId": "testDeploymentId", | ||
| "configurationArn": "arn:aws:greengrass:us-east-1:12345678910:configuration:thinggroup/group1:1", | ||
| "components": { | ||
| "component1": { | ||
| "rootComponent": true, | ||
| "version": "1.0.0" | ||
| } | ||
| }, | ||
| "componentUpdatePolicy": { | ||
| "timeout": 60, | ||
| "action": "NOTIFY_COMPONENTS" | ||
| }, | ||
| "configurationValidationPolicy": { | ||
| "timeout": 20 | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Currently, this returns
truefor the deployments that do not have the update policy set toDeploymentComponentUpdatePolicyAction.NOTIFY_COMPONENTSwhich is wrong. We should discard an update only when the policy is set to notify.