[ISSUE #54 #50] Operator multiple mq cluster && start sequence - #56
[ISSUE #54 #50] Operator multiple mq cluster && start sequence#56linjiemiao wants to merge 2 commits into
Conversation
linjiemiao
commented
Sep 22, 2020
- ensure rocketmq-operator can operator more than one rocketmq cluster;
- make sure nameserver must ready before broker cluster.
2. make sure nameserver must ready before broker cluster.
| size: 1 | ||
| # nameServers is the [ip:port] list of name service | ||
| nameServers: "" | ||
| # rocketMQName is the rocketmq name, must equal to nameserver.spec.rocketMQName and topictransfer.spec.rocketMQName |
There was a problem hiding this comment.
We can not ensure users set insistent name correctly, is there a better way to do this?
There was a problem hiding this comment.
I did this because we don't have a rocketmq resource as the parent resource of the broker and nameserver. Without a common parent controller, we can only specify the connection of the child resource in the spec. So I hope to add a rocketmq api.
There was a problem hiding this comment.
In that case should we add rocketmq higher level api before this PR?
|
still need this |
|
This PR has conflicts with the base branch and cannot be merged. Please rebase or merge the base branch into your branch and resolve the conflicts: git fetch origin
git checkout issue-54-codereview
git rebase origin/main
# resolve conflicts, then:
git push --force-with-leaseThis is a one-time reminder. Feel free to @mention me for a re-review after conflicts are resolved. Automated notification by github-manager-bot |
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Summary
This PR modifies 19 file(s) with 702 lines of diff. No test changes detected — consider adding test coverage.
Automated review by github-manager-bot
Additional notes (not anchored to a changed line)
- [INFO]
README.md:1— Large diff (702 lines). Consider breaking into smaller, focused PRs for easier review. (line outside diff)
| @@ -27,7 +27,6 @@ import ( | |||
| "github.com/apache/rocketmq-operator/pkg/apis" | |||
There was a problem hiding this comment.
No test changes detected alongside source modifications. Consider adding tests to cover the changes.
RockteMQ-AI
left a comment
There was a problem hiding this comment.
Summary
PR received and logged for review. This PR requires detailed code review by a maintainer.
Diff size: 702 lines
Author: linjiemiao (NONE)
Automated review by RockteMQ-AI
| } | ||
|
|
||
| func (sMap *ItemSyncMap) LoadOrStore(key string, value ShareItem) (actual ShareItem, loaded bool) { | ||
| a, loaded := sMap.m.LoadOrStore(key, value) |
There was a problem hiding this comment.
LoadOrStore will panic if the key exists and the stored value is nil, because a.(ShareItem) is an unconditional type assertion. Although ShareItem is a struct (not a pointer), any future refactor to a pointer type would cause a nil panic. More critically, if the underlying sync.Map somehow stores a non-ShareItem value (e.g., due to a bug), this will panic at runtime. Use a safe assertion: actual, _ = a.(ShareItem) to avoid panic.
| return reconcile.Result{}, err | ||
| } | ||
|
|
||
| actualKey := broker.Namespace + "-" + broker.Spec.RocketMQName |
There was a problem hiding this comment.
The broker reconcile loop spins in a tight busy-wait (for { if actual.IsNameServersStrInitialized { break } else { time.Sleep(...) } }) on the controller goroutine. This blocks the entire reconcile goroutine indefinitely, preventing any other reconcile requests from being processed for this controller. This should be replaced with a requeue-based approach (return reconcile.Result{Requeue: true, RequeueAfter: ...}) so the controller manager can continue handling other events.
| return reconcile.Result{}, err | ||
| } | ||
|
|
||
| actualKey := broker.Namespace + "-" + broker.Spec.RocketMQName |
There was a problem hiding this comment.
Race condition: actual is loaded from the sync map into a local variable at line ~134, then the busy-wait loop re-loads actual from the map inside the loop body, but the outer defer at line ~139 always stores the local actual variable back on function exit. If actual.IsNameServersStrInitialized becomes true during the wait loop (set by the nameservice controller), the defer will overwrite the map with the snapshot captured at loop-entry time, potentially clobbering fields like NameServersStr that the nameservice controller wrote.
| @@ -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 | |||
There was a problem hiding this comment.
Inconsistent indentation in the if actual.IsNameServersStrUpdated block: the inner for loop is indented with extra tabs compared to surrounding code. This is a minor formatting issue but indicates the code may not have been run through gofmt, which can cause CI lint failures.
| @@ -253,10 +265,17 @@ func (r *ReconcileBroker) Reconcile(request reconcile.Request) (reconcile.Result | |||
| podNames := getPodNames(podList.Items) | |||
There was a problem hiding this comment.
After the early return when len(podNames) == 0, the reconcile returns without storing the updated actual back to the sync map (the defer will still run, but actual.GroupNum and actual.BrokerClusterName will have been set just before this point). However, actual.NameServersStr may not be populated yet if nameServers is empty and the wait loop hasn't run. The defer stores a potentially incomplete actual, which could overwrite a valid previously-stored value if the nameservice controller already populated it.
| sourceCluster := topicTransfer.Spec.SourceCluster | ||
|
|
||
| nameServer := strings.Split(share.NameServersStr, ";")[0] | ||
| actualKey := topicTransfer.Namespace + "-" + topicTransfer.Spec.RocketMQName |
There was a problem hiding this comment.
strings.Split(actual.NameServersStr, ";")[0] will return an empty string (not panic) if actual.NameServersStr is empty, and the subsequent len(nameServer) < cons.MinIpListLength check handles that. However, if actual was just default-initialized by LoadOrStore (i.e., the nameservice for this rocketMQName has not yet reconciled), the TopicTransfer will silently terminate rather than requeue with an informative error. Consider returning a requeue result instead of terminating.
| 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 |
There was a problem hiding this comment.
Double comment marker on line 40: // // RocketMQ Name, ... — there is a tab and an extra // before the actual comment text. This is a copy-paste artifact and should be // RocketMQ Name, ....
| @@ -93,6 +96,7 @@ spec: | |||
| - volumes | |||
There was a problem hiding this comment.
rocketMQName is now a required field in the CRD. This is a breaking change for any existing Broker CR that does not have this field set. Existing clusters that upgrade to this operator version will have their Broker CRs fail validation. A defaulting webhook or a non-required field with a documented migration path is needed for safe upgrades.
| @@ -73,6 +76,7 @@ spec: | |||
| - storageMode | |||
There was a problem hiding this comment.
Same breaking change as the Broker CRD: making rocketMQName required on NameService CRD will invalidate all existing NameService CRs on upgrade. Needs a migration strategy.
| @@ -100,7 +93,6 @@ func main() { | |||
|
|
|||
There was a problem hiding this comment.
Removing Namespace from manager.Options changes the operator from namespace-scoped to cluster-scoped watching. This is intentional (given the new ClusterRole), but it is a significant behavioral change: the operator will now watch all namespaces, increasing API server load and requiring the new ClusterRole/ClusterRoleBinding to be applied. This should be explicitly documented in the PR and migration notes, and the old namespace-scoped Role/RoleBinding files should be deprecated or removed to avoid confusion.