markap14 commented on code in PR #11677:
URL: https://github.com/apache/nifi/pull/11677#discussion_r4029452993


##########
nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/state/connectors-listing/connectors-listing.effects.ts:
##########
@@ -433,6 +440,82 @@ export class ConnectorsListingEffects {
         )
     );
 
+    openChangeConnectorVersionDialog$ = createEffect(
+        () =>
+            this.actions$.pipe(
+                ofType(openChangeConnectorVersionDialog),
+                map((action) => action.request),
+                switchMap((request) =>
+                    
from(this.extensionTypesService.getConnectorVersionsForType(request.type, 
request.bundle)).pipe(
+                        map(
+                            (response) =>
+                                ({
+                                    fetchRequest: request,
+                                    componentVersions: response.connectorTypes
+                                }) as OpenChangeComponentVersionDialogRequest
+                        ),
+                        catchError((errorResponse: HttpErrorResponse) => {
+                            this.store.dispatch(
+                                ErrorActions.snackBarError({
+                                    error: 
this.errorHelper.getErrorString(errorResponse)
+                                })
+                            );
+                            return EMPTY;
+                        })
+                    )
+                ),
+                tap((request) => {
+                    const dialogRequest = 
this.dialog.open(ChangeComponentVersionDialog, {
+                        ...LARGE_DIALOG,
+                        data: request,
+                        autoFocus: false
+                    });
+
+                    
dialogRequest.componentInstance.changeVersion.pipe(take(1)).subscribe((newVersion)
 => {
+                        this.store.dispatch(
+                            changeConnectorVersion({
+                                request: {
+                                    id: request.fetchRequest.id,
+                                    uri: request.fetchRequest.uri,
+                                    payload: {
+                                        component: {
+                                            bundle: newVersion.bundle,
+                                            id: request.fetchRequest.id
+                                        },
+                                        revision: request.fetchRequest.revision
+                                    }
+                                }
+                            })
+                        );
+                        dialogRequest.close();
+                    });
+                })
+            ),
+        { dispatch: false }
+    );
+
+    changeConnectorVersion$ = createEffect(() =>
+        this.actions$.pipe(
+            ofType(changeConnectorVersion),
+            map((action) => action.request),
+            concatMap((request) =>

Review Comment:
   [gpt-sol-5.6] Addressed in 269a772c478. The listing now passes its `saving` 
state to the connector table, and Change Version is unavailable while that 
state is true. The table test covers the pending-request case.



##########
nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/components/connector/StandardConnectorNode.java:
##########
@@ -1310,6 +1318,126 @@ public Connector getConnector() {
         return connectorDetails.getConnector();
     }
 
+    @Override
+    public void verifyCanReload() {
+        if (!isStopped()) {
+            throw new IllegalStateException("Cannot reload " + this + " 
because its state is " + getCurrentState());
+        }
+    }
+
+    @Override
+    public void verifyCanUpdateBundle(final BundleCoordinate 
incomingCoordinate) {
+        final BundleCoordinate currentCoordinate = getBundleCoordinate();
+        if 
(!currentCoordinate.getGroup().equals(incomingCoordinate.getGroup()) || 
!currentCoordinate.getId().equals(incomingCoordinate.getId())) {
+            throw new IllegalArgumentException("Cannot update " + this + " 
from " + currentCoordinate.getCoordinate() + " to "
+                + incomingCoordinate.getCoordinate() + " because the bundle 
group and artifact must be unchanged");
+        }
+    }
+
+    @Override
+    public void replaceConnector(final Connector replacement, final 
BundleCoordinate replacementCoordinate, final ComponentLog replacementLog) 
throws FlowUpdateException {
+        verifyCanReload();
+
+        final FrameworkConnectorInitializationContext 
replacementInitializationContext = new 
StandardConnectorInitializationContext.Builder()
+            .identifier(identifier)
+            .name(name)
+            .componentLog(replacementLog)
+            .secretsManager(initializationContext.getSecretsManager())
+            .assetManager(initializationContext.getAssetManager())
+            
.componentBundleLookup(initializationContext.getComponentBundleLookup())
+            .build();
+
+        try (final NarCloseable ignored = 
NarCloseable.withComponentNarLoader(replacement.getClass().getClassLoader())) {
+            replacement.initialize(replacementInitializationContext);
+        }
+
+        final WorkingFlowContextState workingContextState = 
acquireWorkingFlowContext();
+        final FrameworkFlowContext workingContext = 
workingContextState.getContext();
+        boolean workingContextReleased = false;
+        try {
+            final Map<String, StepConfiguration> originalActiveConfiguration = 
toConfigurationMap(activeFlowContext.getConfigurationContext().toConnectorConfiguration());
+            final Map<String, StepConfiguration> originalWorkingConfiguration 
= workingContext == null ? originalActiveConfiguration
+                : 
toConfigurationMap(workingContext.getConfigurationContext().toConnectorConfiguration());
+
+            final Map<String, StepConfiguration> activeConfiguration = 
migrateProperties(replacement, originalActiveConfiguration);
+            final Map<String, StepConfiguration> workingConfiguration = 
migrateProperties(replacement, originalWorkingConfiguration);
+            final Bundle bundle = new Bundle(replacementCoordinate.getGroup(), 
replacementCoordinate.getId(), replacementCoordinate.getVersion());
+
+            replaceConfiguration(activeFlowContext.getConfigurationContext(), 
activeConfiguration);

Review Comment:
   [gpt-sol-5.6] Addressed in 269a772c478. Configuration migration is now 
staged in separate contexts before either live context is changed. 
`StandardFlowContext` publishes configuration, bundle, log, and root facade 
through one reload state, and connector metadata is published only after both 
context reloads and callbacks succeed. Failures restore the original working 
context. Tests cover configuration resolution, working-context reload, 
callback, and active-context reload failures.



##########
nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/dto/DtoFactory.java:
##########
@@ -5409,7 +5409,19 @@ public ConnectorDTO createConnectorDto(final 
ConnectorNode connector) {
         dto.setType(connector.getCanonicalClassName());
         dto.setExtensionMissing(connector.isExtensionMissing());
 
-        dto.setBundle(createBundleDto(connector.getBundleCoordinate()));
+        final BundleCoordinate bundleCoordinate = 
connector.getBundleCoordinate();
+        final List<Bundle> availableBundles = 
extensionManager.getBundles(connector.getCanonicalClassName());
+        int compatibleBundleCount = 0;
+        for (final Bundle bundle : availableBundles) {
+            final BundleCoordinate coordinate = 
bundle.getBundleDetails().getCoordinate();
+            if (bundleCoordinate.getGroup().equals(coordinate.getGroup()) && 
bundleCoordinate.getId().equals(coordinate.getId())) {
+                compatibleBundleCount++;
+            }
+        }
+
+        dto.setMultipleVersionsAvailable(connector.isExtensionMissing() ? 
compatibleBundleCount > 0 : compatibleBundleCount > 1);

Review Comment:
   [gpt-sol-5.6] Addressed in 269a772c478. `ConnectorEntityMerger` now follows 
the processor merger pattern and reports `multipleVersionsAvailable=false` when 
any node reports false or null. The merger test covers false, null, and 
all-true node results.



##########
nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/connectors/ui/connector-table/connector-table.component.ts:
##########
@@ -157,6 +159,20 @@ export class ConnectorTable {
         return isConnectorActionAllowed(entity, 'PURGE_FLOWFILES');
     }
 
+    canChangeVersion(entity: ConnectorEntity): boolean {
+        const versionChangeEligibleStates = [
+            ConnectorState.STOPPED,
+            ConnectorState.UPDATED,
+            ConnectorState.UPDATE_FAILED
+        ];
+        return (
+            this.canRead(entity) &&
+            this.canModify(entity) &&
+            versionChangeEligibleStates.includes(entity.component.state as 
ConnectorState) &&

Review Comment:
   [gpt-sol-5.6] Addressed in 269a772c478. `UPDATED` and `UPDATE_FAILED` now 
require an aggregate active-thread count of exactly zero; `STOPPED` retains its 
prior behavior. Tests cover active and quiescent cases for both update states.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to