simonbence commented on code in PR #8726:
URL: https://github.com/apache/nifi/pull/8726#discussion_r1587603716


##########
nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java:
##########
@@ -4022,7 +4027,7 @@ private VersionedFlowSynchronizationContext 
createGroupSynchronizationContext(fi
     }
 
     @Override
-    public void verifyCanSaveToFlowRegistry(final String registryId, final 
String bucketId, final String flowId, final String saveAction) {
+    public void verifyCanSaveToFlowRegistry(final String registryId, final 
String branch, final String bucketId, final String flowId, final String 
saveAction) {

Review Comment:
   Should not the newly created `FlowLocation` used? If I am correct, branch, 
bucket id and flow id covers just the same set of info as `FlowLocation`s state 
covers.



##########
nifi-extension-bundles/nifi-flow-registry-client-bundle/nifi-flow-registry-client-services/src/main/java/org/apache/nifi/registry/flow/NifiRegistryFlowRegistryClient.java:
##########
@@ -149,7 +149,7 @@ public boolean isStorageLocationApplicable(final 
FlowRegistryClientConfiguration
     }
 
     @Override
-    public Set<FlowRegistryBucket> getBuckets(final 
FlowRegistryClientConfigurationContext context) throws FlowRegistryException, 
IOException {
+    public Set<FlowRegistryBucket> getBuckets(final 
FlowRegistryClientConfigurationContext context, final String branch) throws 
FlowRegistryException, IOException {

Review Comment:
   What is the expectation against requests for "non-existing" branches? (In 
case of the NiFiRegistry this should be always the default and I think it is 
planned to enforce this from UI but do we want to have server-side validation 
and failure for cases with different branch or we want branch parameter 
completely ignored for NiFiRegistry)
   
   The question comes from that in `getFlowContents` we do not ignore it. It 
could be shortcutted to be main but it is handled properly, which somewhat 
different from the branch handling in other methods.



##########
nifi-api/src/main/java/org/apache/nifi/registry/flow/FlowRegistryClient.java:
##########
@@ -71,30 +74,82 @@ public interface FlowRegistryClient extends 
ConfigurableComponent {
      */
     boolean isStorageLocationApplicable(FlowRegistryClientConfigurationContext 
context, String location);
 
+    /**
+     * Indicates if the registry supports branching.
+     *
+     * @param context Configuration context
+     * @return true if the registry supports branching, false otherwise
+     */
+    default boolean isBranchingSupported(final 
FlowRegistryClientConfigurationContext context) {
+        return false;
+    }
+
+    /**
+     * Get the available branches. Should return at least one branch that 
matches the response of getDefaultBranch.
+     *
+     * @param context Configuration context
+     * @return the set of available branches
+     *
+     * @throws FlowRegistryException If an issue happens during processing the 
request.
+     * @throws IOException If there is issue with the communication between 
NiFi and the Flow Registry.
+     */
+    default Set<FlowRegistryBranch> getBranches(final 
FlowRegistryClientConfigurationContext context) throws FlowRegistryException, 
IOException {
+        return Set.of(getDefaultBranch(context));
+    }
+
+    /**
+     * Gets the default branch. Must return a non-null FlowRegistryBranch 
instance with a non-null name.

Review Comment:
   I think it might worth mentioning that in case of the impementation does not 
support branching, a default value will be returned for convinience.



##########
nifi-api/src/main/java/org/apache/nifi/registry/flow/CreateBranch.java:
##########
@@ -0,0 +1,53 @@
+/*
+ *
+ *  * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  * contributor license agreements.  See the NOTICE file distributed with
+ *  * this work for additional information regarding copyright ownership.
+ *  * The ASF licenses this file to You under the Apache License, Version 2.0
+ *  * (the "License"); you may not use this file except in compliance with
+ *  * the License.  You may obtain a copy of the License at
+ *  *
+ *  *     http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package org.apache.nifi.registry.flow;
+
+/**
+ * Information for creating a branch in a flow registry.
+ */
+public class CreateBranch {
+
+    private String fromBranch;
+    private String newBranch;
+
+    public CreateBranch() {
+    }
+
+    public CreateBranch(final String fromBranch, final String newBranch) {
+        this.fromBranch = fromBranch;

Review Comment:
   When we do create a branch, is it expected to be branched to the current 
"head" of the fromBranch or what is the expected behaviour? 



##########
nifi-api/src/main/java/org/apache/nifi/registry/flow/FlowRegistryClient.java:
##########
@@ -71,30 +74,82 @@ public interface FlowRegistryClient extends 
ConfigurableComponent {
      */
     boolean isStorageLocationApplicable(FlowRegistryClientConfigurationContext 
context, String location);
 
+    /**
+     * Indicates if the registry supports branching.
+     *
+     * @param context Configuration context
+     * @return true if the registry supports branching, false otherwise
+     */
+    default boolean isBranchingSupported(final 
FlowRegistryClientConfigurationContext context) {
+        return false;
+    }
+
+    /**
+     * Get the available branches. Should return at least one branch that 
matches the response of getDefaultBranch.
+     *
+     * @param context Configuration context
+     * @return the set of available branches
+     *
+     * @throws FlowRegistryException If an issue happens during processing the 
request.
+     * @throws IOException If there is issue with the communication between 
NiFi and the Flow Registry.
+     */
+    default Set<FlowRegistryBranch> getBranches(final 
FlowRegistryClientConfigurationContext context) throws FlowRegistryException, 
IOException {
+        return Set.of(getDefaultBranch(context));
+    }
+
+    /**
+     * Gets the default branch. Must return a non-null FlowRegistryBranch 
instance with a non-null name.
+     *
+     * @param context Configuration context
+     * @return the default branch
+     *
+     * @throws FlowRegistryException If an issue happens during processing the 
request.
+     * @throws IOException If there is issue with the communication between 
NiFi and the Flow Registry.
+     */
+    default FlowRegistryBranch getDefaultBranch(final 
FlowRegistryClientConfigurationContext context) throws FlowRegistryException, 
IOException {
+        final FlowRegistryBranch branch = new FlowRegistryBranch();
+        branch.setName(DEFAULT_BRANCH_NAME);
+        return branch;
+    }
+
+    /**
+     * Creates a new branch from a given branch.
+     *
+     * @param context Configuration context
+     * @param createBranch the info for creating the branch
+     *
+     * @throws FlowRegistryException If an issue happens during processing the 
request.
+     * @throws IOException If there is issue with the communication between 
NiFi and the Flow Registry.
+     */
+    default void createBranch(FlowRegistryClientConfigurationContext context, 
final CreateBranch createBranch) throws FlowRegistryException, IOException {

Review Comment:
   Bucket creation is not supported in the client but spared for the actaul 
registry service. Is not this out of the concept of the client as well?



##########
nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java:
##########
@@ -4040,14 +4045,20 @@ public void verifyCanSaveToFlowRegistry(final String 
registryId, final String bu
 
                 // Flow ID matches. We want to publish the Process Group as 
the next version of the Flow, so we must
                 // ensure that all other parameters match as well.
+
+                if (branch != null && !Objects.equals(branch, 
vci.getBranch())) {

Review Comment:
   This two statement could be merged into one with the following way:
   - `FlowLocation` might be able to proviede a `BucketLocation` instance (like 
a partial path)
   - We could compare `BucketLocation` instnaces
   I think that would simplify this, might communicate the intent in a more 
accurate manner and as we have the same error message we would not even loose 
details



##########
nifi-api/src/main/java/org/apache/nifi/registry/flow/BucketLocation.java:
##########
@@ -0,0 +1,54 @@
+/*
+ *
+ *  * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  * contributor license agreements.  See the NOTICE file distributed with
+ *  * this work for additional information regarding copyright ownership.
+ *  * The ASF licenses this file to You under the Apache License, Version 2.0
+ *  * (the "License"); you may not use this file except in compliance with
+ *  * the License.  You may obtain a copy of the License at
+ *  *
+ *  *     http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package org.apache.nifi.registry.flow;
+
+/**
+ * Information for locating a bucket in a flow registry.
+ */
+public class BucketLocation {
+
+    private String branch;

Review Comment:
   Is there any contract or expectation against the relationship between branch 
and bucket? Based on what I saw in the code, I assume the top level 
organization is the branch, so buckts are _witnin_ the branches. (I might be 
wrong, I do not remember seeing explicit mention of this) Is there any 
expectations like a bucket must exists under every brunch (but the flows/flow 
versions might differ)?
   
   If this level structure stands, it can have a negative affect on the user 
experience as buckets currently cannot be created from NiFi UI. So for example 
I have a flow F1 within bucket B1 which are in the "main" branch. Assume I want 
to move to a "dev" branch with a new version of F1. Multiple things might 
happen depending on our purposes:
   - If branches and buckets are ortogonal, the bucket will be available for 
every branches
   - If buckets (already existing under other branches) are created on the need 
basis, registry implementations needs to know about this expectation and 
support this
   - If we expect buckets to be in place, currently the users needs to move to 
the registry server beforehand and create the given bucket before committing.
   
   I think based on the code I have a good educated guess about the idea but I 
would find it beneficial to have a description about this somewhere (either in 
documentation or javadoc, I am not sure)



##########
nifi-api/src/main/java/org/apache/nifi/registry/flow/FlowRegistryBranch.java:
##########
@@ -0,0 +1,52 @@
+/*
+ *
+ *  * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  * contributor license agreements.  See the NOTICE file distributed with
+ *  * this work for additional information regarding copyright ownership.
+ *  * The ASF licenses this file to You under the Apache License, Version 2.0
+ *  * (the "License"); you may not use this file except in compliance with
+ *  * the License.  You may obtain a copy of the License at
+ *  *
+ *  *     http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+package org.apache.nifi.registry.flow;
+
+import java.util.Objects;
+
+public class FlowRegistryBranch {

Review Comment:
   Can it matter what is the parent branch? Or this is a detail to the registry 
implementation and we do not wish to know?



##########
nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/StandardFlowRegistryClientNode.java:
##########
@@ -369,19 +391,21 @@ private RegisteredFlowSnapshot fetchFlowContents(final 
FlowRegistryClientUserCon
                                                      final boolean 
fetchRemoteFlows) throws FlowRegistryException {
 
         final String storageLocation = coordinates.getStorageLocation();
+        final String branch = coordinates.getBranch();
         final String bucketId = coordinates.getBucketId();
         final String flowId = coordinates.getFlowId();
         final String version = coordinates.getVersion();
+        final FlowVersionLocation flowVersionLocation = new 
FlowVersionLocation(branch, bucketId, flowId, version);
 
         final List<FlowRegistryClientNode> clientNodes = 
getRegistryClientsForInternalFlow(storageLocation);
         for (final FlowRegistryClientNode clientNode : clientNodes) {
             try {
-                logger.debug("Attempting to fetch flow for Bucket [{}] Flow 
[{}] Version [{}] using {}", bucketId, flowId, version, clientNode);
-                final FlowSnapshotContainer snapshotContainer = 
clientNode.getFlowContents(context, bucketId, flowId, version, 
fetchRemoteFlows);
+                logger.debug("Attempting to fetch flow from branch [{}] for 
Bucket [{}] Flow [{}] Version [{}] using {}", branch, bucketId, flowId, 
version, clientNode);
+                final FlowSnapshotContainer snapshotContainer = 
clientNode.getFlowContents(context, flowVersionLocation, fetchRemoteFlows);
                 final RegisteredFlowSnapshot snapshot = 
snapshotContainer.getFlowSnapshot();
                 coordinates.setRegistryId(clientNode.getIdentifier());
 
-                logger.debug("Successfully fetched flow for Bucket [{}] Flow 
[{}] Version [{}] using {}", bucketId, flowId, version, clientNode);
+                logger.debug("Successfully fetched flow from branch [{}] for 
Bucket [{}] Flow [{}] Version [{}] using {}", branch, bucketId, flowId, 
version, clientNode);

Review Comment:
   Minor: other parts of the location start with upper case. Should not branch 
do that too?



##########
nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/FlowAnalyzingRegistryClientNode.java:
##########
@@ -401,13 +401,33 @@ public boolean isStorageLocationApplicable(final String 
location) {
     }
 
     @Override
-    public Set<FlowRegistryBucket> getBuckets(final 
FlowRegistryClientUserContext context) throws FlowRegistryException, 
IOException {
-        return node.getBuckets(context);
+    public boolean isBranchingSupported() {
+        return node.isBranchingSupported();
     }
 
     @Override
-    public FlowRegistryBucket getBucket(final FlowRegistryClientUserContext 
context, final String bucketId) throws FlowRegistryException, IOException {
-        return node.getBucket(context, bucketId);
+    public Set<FlowRegistryBranch> getBranches(final 
FlowRegistryClientUserContext context) throws FlowRegistryException, 
IOException {
+        return node.getBranches(context);
+    }
+
+    @Override
+    public FlowRegistryBranch getDefaultBranch(final 
FlowRegistryClientUserContext context) throws FlowRegistryException, 
IOException {
+        return node.getDefaultBranch(context);
+    }
+
+    @Override
+    public void createBranch(final FlowRegistryClientUserContext context, 
final CreateBranch createBranch) throws FlowRegistryException, IOException {

Review Comment:
   Up to this point, the `FlowAnalyzingRegistryClientNode` did not have methods 
with argumetns serving as "command object". In cases where it depended on more 
complex structures, like in case of `RegisteredFlow`, these arguments were data 
driven (here: `RegisteredFlow` and not `RegisterFlow`). I think this makes the 
interface into somewhat inconsistent. I would suggest with providing two branch 
representation, even if they are Strings or their own type (as I see other 
methods go with String based representation, so if you go with their specific 
type, I suggest to update those methods as well)



-- 
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