RockteMQ-AI commented on code in PR #56:
URL: https://github.com/apache/rocketmq-operator/pull/56#discussion_r3902494704


##########
pkg/share/share.go:
##########
@@ -18,19 +18,45 @@
 // Package share defines some variables shared by different packages
 package share
 
+import "sync"
+
 var (

Review Comment:
   `ShareItem` is a value type (struct), not a pointer. `LoadOrStore` and 
`Load` return a copy; mutations to fields like `actual.NameServersStr` are 
local until `Store` is explicitly called. When broker and nameservice 
controllers reconcile concurrently for the same key, they each get independent 
copies, mutate them, and the last `Store` wins — silently dropping the other's 
changes (e.g., `IsNameServersStrInitialized` could be overwritten back to 
`false`). Use `*ShareItem` (pointer) or a mutex-guarded struct to ensure atomic 
read-modify-write.



##########
pkg/controller/broker/broker_controller.go:
##########
@@ -131,31 +131,43 @@ func (r *ReconcileBroker) Reconcile(request 
reconcile.Request) (reconcile.Result
                return reconcile.Result{}, err
        }
 
+       actualKey := broker.Namespace + "-" + broker.Spec.RocketMQName
+       actual, _ := share.GetInstance().LoadOrStore(actualKey, 
share.ShareItem{})
+       defer func() {
+               reqLogger.Info("Broker actualKey:" + actualKey + " 
actual.NameServerStr:" + actual.NameServersStr +
+                       " actual.BrokerClusterName:" + actual.BrokerClusterName 
+ " IsNameServersStrInitialized:" + 
strconv.FormatBool(actual.IsNameServersStrInitialized))
+               share.GetInstance().Store(actualKey, actual)
+       }()
+
+       var groupNum int
        if broker.Status.Size == 0 {
-               share.GroupNum = broker.Spec.Size
+               groupNum = broker.Spec.Size
        } else {
-               share.GroupNum = broker.Status.Size
+               groupNum = broker.Status.Size
        }

Review Comment:
   Infinite blocking `for` loop with `time.Sleep` has no timeout, context 
cancellation, or requeue. If the NameServer never becomes ready, this 
permanently blocks a controller worker goroutine, starving all other reconcile 
requests. Replace with `return reconcile.Result{RequeueAfter: ...}, nil` so the 
work is re-enqueued without blocking.



##########
deploy/crds/rocketmq_v1alpha1_nameservice_crd.yaml:
##########
@@ -73,6 +76,7 @@ spec:
           - storageMode
           - hostPath
           - volumeClaimTemplates
+          - rocketMQName

Review Comment:
   Same backward-compatibility break as the Broker CRD: `rocketMQName` is added 
to `required`, which will reject any existing NameService CR that lacks the 
field upon upgrade.



##########
deploy/crds/rocketmq_v1alpha1_broker_crd.yaml:
##########
@@ -93,6 +96,7 @@ spec:
           - volumes
           - volumeClaimTemplates
           - scalePodName
+          - rocketMQName

Review Comment:
   `rocketMQName` is added to the `required` list. Any existing Broker CR that 
does not include this field will fail validation after CRD upgrade, breaking 
backward compatibility. Either provide a default value via an admission webhook 
/ mutating webhook, remove it from `required`, or use a conversion/migration 
step for existing resources.



##########
deploy/clusterrole_binding.yaml:
##########
@@ -0,0 +1,27 @@
+# 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.
+
+kind: ClusterRoleBinding
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+  name: rocketmq-operator
+subjects:
+  - kind: ServiceAccount
+    name: rocketmq-operator

Review Comment:
   The ServiceAccount namespace is hardcoded to `default`. If the operator is 
deployed to any other namespace, the binding will reference a non-existent 
ServiceAccount and RBAC will deny all API calls. Make this configurable (e.g., 
via Kustomize or Helm templating).



##########
pkg/controller/broker/broker_controller.go:
##########
@@ -189,8 +201,8 @@ func (r *ReconcileBroker) Reconcile(request 
reconcile.Request) (reconcile.Result
        // Check for name server scaling
        if broker.Spec.AllowRestart {
                // The following code will restart all brokers to update 
NAMESRV_ADDR env
-               if share.IsNameServersStrUpdated {
-                       for brokerGroupIndex := 0; brokerGroupIndex < 
broker.Spec.Size; brokerGroupIndex++ {
+               if actual.IsNameServersStrUpdated {

Review Comment:
   Indentation regression: the `for` loop inside the `if 
actual.IsNameServersStrUpdated` block has an extra tab, misaligning it from the 
enclosing `if`. This is likely a merge artifact and should be corrected to 
maintain readability.



##########
pkg/controller/broker/broker_controller.go:
##########
@@ -454,9 +475,13 @@ func (r *ReconcileBroker) getBrokerStatefulSet(broker 
*rocketmqv1alpha1.Broker,
 }
 
 func getENV(broker *rocketmqv1alpha1.Broker, replicaIndex int, 
brokerGroupIndex int)  []corev1.EnvVar {
+

Review Comment:
   `getENV` calls `LoadOrStore(actualKey, share.ShareItem{})` which will insert 
an empty `ShareItem` (all zero values) if the key does not yet exist. If the 
broker reconciles before the nameservice controller has stored real values, 
`NameServersStr` will be empty and broker pods will be created with an invalid 
`NAMESRV_ADDR`. Consider using `Load` instead and returning an error / requeue 
when the key is absent.



##########
pkg/controller/nameservice/nameservice_controller.go:
##########
@@ -174,7 +174,23 @@ func (r *ReconcileNameService) 
updateNameServiceStatus(instance *rocketmqv1alpha
        }
        hostIps := getNameServers(podList.Items)
 
+       if len(hostIps) != int(instance.Spec.Size) || len(hostIps) == 0 {

Review Comment:
   Early return when `len(hostIps) != instance.Spec.Size` happens before the 
deferred `Store`, so no `ShareItem` is created for this key. This is correct 
behavior, but if the nameservice never reaches full size (e.g., a node 
shortage), brokers waiting on `IsNameServersStrInitialized` will block 
indefinitely (see broker_controller.go infinite loop issue). Consider setting a 
partial-readiness indicator or adding a timeout.



##########
deploy/cluster_role.yaml:
##########
@@ -0,0 +1,72 @@
+# 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.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  creationTimestamp: null
+  name: rocketmq-operator
+rules:
+  - apiGroups:
+      - ""
+    resources:
+      - pods
+      - services
+      - endpoints
+      - persistentvolumeclaims
+      - events
+      - configmaps
+      - secrets
+      - pods/exec
+    verbs:
+      - '*'
+  - apiGroups:
+      - ""
+    resources:
+      - namespaces
+    verbs:
+      - get
+  - apiGroups:
+      - apps
+    resources:
+      - deployments
+      - daemonsets
+      - replicasets
+      - statefulsets
+    verbs:
+      - '*'
+  - apiGroups:
+      - monitoring.coreos.com
+    resources:
+      - servicemonitors
+    verbs:
+      - get
+      - create
+  - apiGroups:
+      - apps
+    resourceNames:
+      - rocketmq-operator
+    resources:
+      - deployments/finalizers
+    verbs:
+      - update
+  - apiGroups:
+      - rocketmq.apache.org
+    resources:

Review Comment:
   `pods/exec` is listed under the `rocketmq.apache.org` API group, which is 
incorrect — `pods/exec` belongs to the core (`""`) API group and is already 
listed there (line 30). The duplicate under the custom API group is meaningless 
and should be removed.



##########
pkg/apis/rocketmq/v1alpha1/topictransfer_types.go:
##########
@@ -37,6 +37,8 @@ type TopicTransferSpec struct {
        SourceCluster string `json:"sourceCluster,omitempty"`
        // The cluster where the topic will be transferred to
        TargetCluster string `json:"targetCluster,omitempty"`
+       //      // RocketMQ Name, the broker and nameserver in the same cluster 
must be filled with the same name

Review Comment:
   Malformed comment: `//       // RocketMQ Name...` contains a stray tab and 
duplicate `//` prefix, likely a copy-paste artifact. Clean up to `// RocketMQ 
Name, the broker and nameserver in the same cluster must be filled with the 
same name`.



##########
pkg/controller/topictransfer/topictransfer_controller.go:
##########
@@ -127,7 +127,9 @@ func (r *ReconcileTopicTransfer) Reconcile(request 
reconcile.Request) (reconcile
        targetCluster := topicTransfer.Spec.TargetCluster
        sourceCluster := topicTransfer.Spec.SourceCluster
 
-       nameServer := strings.Split(share.NameServersStr, ";")[0]
+       actualKey := topicTransfer.Namespace + "-" + 
topicTransfer.Spec.RocketMQName

Review Comment:
   `LoadOrStore` with an empty `ShareItem` means if the TopicTransfer 
reconciles before any NameService has populated the map, an empty entry is 
persisted. `strings.Split("", ";")[0]` returns `""` which is caught by the 
length check, but the stale empty entry remains in the map. Use `Load` and 
requeue if the key is not found.



##########
pkg/controller/broker/broker_controller.go:
##########
@@ -276,6 +295,17 @@ func (r *ReconcileBroker) Reconcile(request 
reconcile.Request) (reconcile.Result
                cmd = []string{"/bin/bash", "-c", MakeConfigDirCommand + " && " 
+ ChmodDirCommand + " && " + topicsCommand + " && " + subscriptionGroupCommand}
        }
 
+       // Update status.Nodes if needed

Review Comment:
   The new `len(podNames) == 0` guard returns early with a requeue, but the 
subsequent status update at line 302 adds a `len(broker.Status.Nodes) != 0` 
guard that prevents clearing `Status.Nodes` when all pods are gone. This 
asymmetry means the status can never reflect a fully-scaled-down state; if that 
is intentional (safety), document it.



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