@@ -13,7 +13,11 @@ import {
1313 updateContainer as apiUpdateContainer ,
1414} from '../../services/container-actions' ;
1515import type { Container } from '../../types/container' ;
16- import { getContainerActionKey , hasTrackedContainerAction } from '../../utils/container-action-key' ;
16+ import {
17+ getContainerActionIdentityKey ,
18+ getContainerActionKey ,
19+ hasTrackedContainerAction ,
20+ } from '../../utils/container-action-key' ;
1721import {
1822 createContainerUpdateBatchId ,
1923 formatContainerUpdateStartedCountMessage ,
@@ -35,7 +39,7 @@ interface ContainerActionGroup {
3539 containers : Container [ ] ;
3640}
3741
38- type ContainerActionTarget = string | Pick < Container , 'id' | 'name' | 'updateOperation' > ;
42+ type ContainerActionTarget = string | Pick < Container , 'id' | 'name' | 'server' | ' updateOperation'> ;
3943
4044interface UseContainerActionsInput {
4145 activeDetailTab : Readonly < Ref < string > > ;
@@ -91,54 +95,73 @@ function hasPendingContainerAction(
9195 target : ContainerActionTarget ,
9296 actionPending : Readonly < Ref < Map < string , Container > > > ,
9397) {
94- const name = typeof target === 'string' ? target : target . name ;
95- return typeof name === 'string' && name . length > 0 && actionPending . value . has ( name ) ;
98+ const pendingKey = resolveContainerActionTargetKey ( target ) ;
99+ if ( pendingKey && actionPending . value . has ( pendingKey ) ) {
100+ return true ;
101+ }
102+
103+ const identityKey = typeof target === 'string' ? target : getContainerActionIdentityKey ( target ) ;
104+ if ( ! identityKey ) {
105+ return false ;
106+ }
107+
108+ return [ ...actionPending . value . values ( ) ] . some ( ( snapshot ) => {
109+ return typeof target === 'string'
110+ ? snapshot . name === identityKey
111+ : getContainerActionIdentityKey ( snapshot ) === identityKey ;
112+ } ) ;
96113}
97114
98115function hasInProgressUpdateOperation (
99116 target : ContainerActionTarget ,
100117 containers : Readonly < Ref < Container [ ] > > ,
101118) {
102119 const targetId = typeof target === 'string' ? undefined : target . id ;
103- const targetName = typeof target === 'string' ? target : target . name ;
120+ const targetIdentityKey =
121+ typeof target === 'string' ? target : getContainerActionIdentityKey ( target ) ;
104122
105123 return containers . value . some ( ( container ) => {
106- const matches = targetId ? container . id === targetId : container . name === targetName ;
107- return matches && container . updateOperation ?. status === 'in-progress' ;
124+ const matchesId = Boolean ( targetId && container . id === targetId ) ;
125+ const matchesIdentity =
126+ typeof target === 'string'
127+ ? container . name === targetIdentityKey
128+ : getContainerActionIdentityKey ( container ) === targetIdentityKey ;
129+ return ( matchesId || matchesIdentity ) && container . updateOperation ?. status === 'in-progress' ;
108130 } ) ;
109131}
110132
111133function markPendingActionState ( args : {
112134 actionPending : Ref < Map < string , Container > > ;
113135 actionPendingLifecycleModes : Ref < Map < string , PendingActionLifecycleMode > > ;
114136 actionPendingLifecycleObserved : Ref < Set < string > > ;
115- startPolling : ( name : string ) => void ;
116- name : string ;
137+ startPolling : ( pendingKey : string ) => void ;
138+ pendingKey : string ;
117139 snapshot ?: Container ;
118140 mode : PendingActionLifecycleMode ;
119141} ) {
120142 if ( ! args . snapshot ) {
121143 return ;
122144 }
123145
124- args . actionPending . value . set ( args . name , args . snapshot ) ;
125- args . actionPendingLifecycleModes . value . set ( args . name , args . mode ) ;
146+ args . actionPending . value . set ( args . pendingKey , args . snapshot ) ;
147+ args . actionPendingLifecycleModes . value . set ( args . pendingKey , args . mode ) ;
126148
127149 const nextObserved = new Set ( args . actionPendingLifecycleObserved . value ) ;
128150 if ( args . mode === 'update' ) {
129- nextObserved . delete ( args . name ) ;
151+ nextObserved . delete ( args . pendingKey ) ;
130152 } else {
131- nextObserved . add ( args . name ) ;
153+ nextObserved . add ( args . pendingKey ) ;
132154 }
133155 args . actionPendingLifecycleObserved . value = nextObserved ;
134- args . startPolling ( args . name ) ;
156+ args . startPolling ( args . pendingKey ) ;
135157}
136158
137159async function executeContainerActionState ( args : {
138160 containerActionsEnabled : boolean ;
139161 containerActionsDisabledReason : string ;
140162 containerId ?: string ;
141163 actionKey : string ;
164+ pendingKey : string ;
142165 name : string ;
143166 actionInProgress : Ref < Set < string > > ;
144167 inputError : Ref < string | null > ;
@@ -149,7 +172,7 @@ async function executeContainerActionState(args: {
149172 actionPending : Ref < Map < string , Container > > ;
150173 actionPendingLifecycleModes : Ref < Map < string , PendingActionLifecycleMode > > ;
151174 actionPendingLifecycleObserved : Ref < Set < string > > ;
152- startPolling : ( name : string ) => void ;
175+ startPolling : ( pendingKey : string ) => void ;
153176 selectedContainerId : string | undefined ;
154177 activeDetailTab : string ;
155178 refreshActionTabData : ( ) => Promise < void > ;
@@ -184,7 +207,7 @@ async function executeContainerActionState(args: {
184207 actionPendingLifecycleModes : args . actionPendingLifecycleModes ,
185208 actionPendingLifecycleObserved : args . actionPendingLifecycleObserved ,
186209 startPolling : args . startPolling ,
187- name : args . name ,
210+ pendingKey : args . pendingKey ,
188211 snapshot,
189212 mode : 'update' ,
190213 } ) ;
@@ -200,7 +223,7 @@ async function executeContainerActionState(args: {
200223 actionPendingLifecycleModes : args . actionPendingLifecycleModes ,
201224 actionPendingLifecycleObserved : args . actionPendingLifecycleObserved ,
202225 startPolling : args . startPolling ,
203- name : args . name ,
226+ pendingKey : args . pendingKey ,
204227 snapshot,
205228 mode : args . pendingLifecycleMode ?? 'presence' ,
206229 } ) ;
@@ -372,7 +395,10 @@ function getPersistedTargetSequence(
372395) {
373396 const liveContainer =
374397 containers . find ( ( container ) => container . id === target . id ) ??
375- containers . find ( ( container ) => container . name === target . name ) ;
398+ containers . find (
399+ ( container ) =>
400+ getContainerActionIdentityKey ( container ) === getContainerActionIdentityKey ( target ) ,
401+ ) ;
376402 const sequence = getPersistedUpdateBatchSequence (
377403 liveContainer ?. updateOperation ?? target . updateOperation ,
378404 ) ;
@@ -570,25 +596,25 @@ function clearPendingActionState(args: {
570596 actionPendingLifecycleObserved : Ref < Set < string > > ;
571597 groupUpdateQueue : Ref < Set < string > > ;
572598 groupUpdateSequence : Ref < Map < string , GroupUpdateSequenceEntry > > ;
573- name : string ;
599+ pendingKey : string ;
574600} ) {
575- const snapshot = args . actionPending . value . get ( args . name ) ;
601+ const snapshot = args . actionPending . value . get ( args . pendingKey ) ;
576602 if ( snapshot ?. id ) {
577603 setGroupUpdateQueueValue ( args . groupUpdateQueue , [ snapshot . id ] , false ) ;
578604 const nextSequence = new Map ( args . groupUpdateSequence . value ) ;
579605 nextSequence . delete ( snapshot . id ) ;
580606 args . groupUpdateSequence . value = nextSequence ;
581607 }
582- args . actionPending . value . delete ( args . name ) ;
583- args . actionPendingStartTimes . value . delete ( args . name ) ;
584- args . actionPendingLifecycleModes . value . delete ( args . name ) ;
608+ args . actionPending . value . delete ( args . pendingKey ) ;
609+ args . actionPendingStartTimes . value . delete ( args . pendingKey ) ;
610+ args . actionPendingLifecycleModes . value . delete ( args . pendingKey ) ;
585611 const nextObserved = new Set ( args . actionPendingLifecycleObserved . value ) ;
586- nextObserved . delete ( args . name ) ;
612+ nextObserved . delete ( args . pendingKey ) ;
587613 args . actionPendingLifecycleObserved . value = nextObserved ;
588614}
589615
590616export function isPendingUpdateSettled ( args : {
591- name : string ;
617+ pendingKey : string ;
592618 now : number ;
593619 startTime : number ;
594620 liveContainer ?: Container ;
@@ -603,7 +629,7 @@ export function isPendingUpdateSettled(args: {
603629 args . liveContainer . status !== expectedStatus ;
604630 if ( observedLifecycleSignal ) {
605631 const nextObserved = new Set ( args . actionPendingLifecycleObserved . value ) ;
606- nextObserved . add ( args . name ) ;
632+ nextObserved . add ( args . pendingKey ) ;
607633 args . actionPendingLifecycleObserved . value = nextObserved ;
608634 }
609635
@@ -623,7 +649,7 @@ export function isPendingUpdateSettled(args: {
623649 }
624650
625651 return (
626- args . actionPendingLifecycleObserved . value . has ( args . name ) ||
652+ args . actionPendingLifecycleObserved . value . has ( args . pendingKey ) ||
627653 args . now - args . startTime >= PENDING_UPDATE_GRACE_MS
628654 ) ;
629655}
@@ -640,21 +666,36 @@ function prunePendingActionsState(args: {
640666 pollTimeout : number ;
641667 stopPendingActionsPolling : ( ) => void ;
642668} ) {
643- const liveContainersByName = new Map (
644- args . containers . value . map ( ( container ) => [ container . name , container ] as const ) ,
645- ) ;
646- for ( const [ name , startTime ] of args . actionPendingStartTimes . value . entries ( ) ) {
647- const liveContainer = liveContainersByName . get ( name ) ;
648- const pendingMode = args . actionPendingLifecycleModes . value . get ( name ) ;
669+ const liveContainersByActionKey = new Map < string , Container > ( ) ;
670+ const liveContainersByIdentityKey = new Map < string , Container > ( ) ;
671+
672+ for ( const container of args . containers . value ) {
673+ const actionKey = getContainerActionKey ( container ) ;
674+ if ( actionKey ) {
675+ liveContainersByActionKey . set ( actionKey , container ) ;
676+ }
677+ const identityKey = getContainerActionIdentityKey ( container ) ;
678+ if ( identityKey ) {
679+ liveContainersByIdentityKey . set ( identityKey , container ) ;
680+ }
681+ }
682+
683+ for ( const [ pendingKey , startTime ] of args . actionPendingStartTimes . value . entries ( ) ) {
684+ const snapshot = args . actionPending . value . get ( pendingKey ) ;
685+ const snapshotIdentityKey = snapshot ? getContainerActionIdentityKey ( snapshot ) : '' ;
686+ const liveContainer =
687+ liveContainersByActionKey . get ( pendingKey ) ??
688+ ( snapshotIdentityKey ? liveContainersByIdentityKey . get ( snapshotIdentityKey ) : undefined ) ;
689+ const pendingMode = args . actionPendingLifecycleModes . value . get ( pendingKey ) ;
649690 const timedOut = args . now - startTime > args . pollTimeout ;
650691 const settled =
651692 pendingMode === 'update'
652693 ? isPendingUpdateSettled ( {
653- name ,
694+ pendingKey ,
654695 now : args . now ,
655696 startTime,
656697 liveContainer,
657- snapshot : args . actionPending . value . get ( name ) ,
698+ snapshot,
658699 actionPendingLifecycleObserved : args . actionPendingLifecycleObserved ,
659700 } )
660701 : Boolean ( liveContainer ) ;
@@ -667,7 +708,7 @@ function prunePendingActionsState(args: {
667708 actionPendingLifecycleObserved : args . actionPendingLifecycleObserved ,
668709 groupUpdateQueue : args . groupUpdateQueue ,
669710 groupUpdateSequence : args . groupUpdateSequence ,
670- name ,
711+ pendingKey ,
671712 } ) ;
672713 }
673714 }
@@ -694,14 +735,14 @@ async function pollPendingActionsState(args: {
694735}
695736
696737function startPollingState ( args : {
697- name : string ;
738+ pendingKey : string ;
698739 actionPendingStartTimes : Ref < Map < string , number > > ;
699740 pendingActionsPollTimer : Ref < ReturnType < typeof setInterval > | null > ;
700741 pollInterval : number ;
701742 pollPendingActions : ( ) => Promise < void > ;
702743} ) {
703- if ( ! args . actionPendingStartTimes . value . has ( args . name ) ) {
704- args . actionPendingStartTimes . value . set ( args . name , Date . now ( ) ) ;
744+ if ( ! args . actionPendingStartTimes . value . has ( args . pendingKey ) ) {
745+ args . actionPendingStartTimes . value . set ( args . pendingKey , Date . now ( ) ) ;
705746 }
706747 if ( args . pendingActionsPollTimer . value ) {
707748 return ;
@@ -1077,9 +1118,9 @@ export function useContainerActions(input: UseContainerActionsInput) {
10771118 } ) ;
10781119 }
10791120
1080- function startPolling ( name : string ) {
1121+ function startPolling ( pendingKey : string ) {
10811122 startPollingState ( {
1082- name ,
1123+ pendingKey ,
10831124 actionPendingStartTimes,
10841125 pendingActionsPollTimer,
10851126 pollInterval : PENDING_ACTIONS_POLL_INTERVAL_MS ,
@@ -1223,11 +1264,13 @@ export function useContainerActions(input: UseContainerActionsInput) {
12231264 options ?. containerId ,
12241265 ) ;
12251266 const actionKey = containerId ?? resolveContainerActionTargetKey ( target ) ;
1267+ const pendingKey = resolveContainerActionTargetKey ( target ) ;
12261268 return executeContainerActionState ( {
12271269 containerActionsEnabled : containerActionsEnabled . value ,
12281270 containerActionsDisabledReason : containerActionsDisabledReason . value ,
12291271 containerId,
12301272 actionKey,
1273+ pendingKey,
12311274 name,
12321275 actionInProgress,
12331276 inputError : input . error ,
0 commit comments