From 42576c8823228ee0f0cc266dcf97cf4a60f00694 Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Fri, 28 Feb 2025 15:39:19 -0500 Subject: [PATCH 1/4] update unified tests --- ...ed-emit-topology-changed-before-close.json | 88 ++++++++++++++ ...ced-emit-topology-changed-before-close.yml | 49 ++++++++ .../unified/logging-loadbalanced.json | 16 +++ .../unified/logging-loadbalanced.yml | 7 ++ ...et-emit-topology-changed-before-close.json | 89 +++++++++++++++ ...set-emit-topology-changed-before-close.yml | 49 ++++++++ ...ed-emit-topology-changed-before-close.json | 108 ++++++++++++++++++ ...ded-emit-topology-changed-before-close.yml | 62 ++++++++++ ...ne-emit-topology-changed-before-close.json | 97 ++++++++++++++++ ...one-emit-topology-changed-before-close.yml | 55 +++++++++ 10 files changed, 620 insertions(+) create mode 100644 testdata/server-discovery-and-monitoring/unified/loadbalanced-emit-topology-changed-before-close.json create mode 100644 testdata/server-discovery-and-monitoring/unified/loadbalanced-emit-topology-changed-before-close.yml create mode 100644 testdata/server-discovery-and-monitoring/unified/replicaset-emit-topology-changed-before-close.json create mode 100644 testdata/server-discovery-and-monitoring/unified/replicaset-emit-topology-changed-before-close.yml create mode 100644 testdata/server-discovery-and-monitoring/unified/sharded-emit-topology-changed-before-close.json create mode 100644 testdata/server-discovery-and-monitoring/unified/sharded-emit-topology-changed-before-close.yml create mode 100644 testdata/server-discovery-and-monitoring/unified/standalone-emit-topology-changed-before-close.json create mode 100644 testdata/server-discovery-and-monitoring/unified/standalone-emit-topology-changed-before-close.yml diff --git a/testdata/server-discovery-and-monitoring/unified/loadbalanced-emit-topology-changed-before-close.json b/testdata/server-discovery-and-monitoring/unified/loadbalanced-emit-topology-changed-before-close.json new file mode 100644 index 0000000000..30c0657630 --- /dev/null +++ b/testdata/server-discovery-and-monitoring/unified/loadbalanced-emit-topology-changed-before-close.json @@ -0,0 +1,88 @@ +{ + "description": "loadbalanced-emit-topology-description-changed-before-close", + "schemaVersion": "1.20", + "runOnRequirements": [ + { + "topologies": [ + "load-balanced" + ], + "minServerVersion": "4.4" + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "topologyOpeningEvent", + "topologyClosedEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 2 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "events": [ + { + "topologyOpeningEvent": {} + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": {} + } + }, + { + "topologyDescriptionChangedEvent": { + "newDescription": { + "type": "LoadBalanced" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/testdata/server-discovery-and-monitoring/unified/loadbalanced-emit-topology-changed-before-close.yml b/testdata/server-discovery-and-monitoring/unified/loadbalanced-emit-topology-changed-before-close.yml new file mode 100644 index 0000000000..c919a8cf8b --- /dev/null +++ b/testdata/server-discovery-and-monitoring/unified/loadbalanced-emit-topology-changed-before-close.yml @@ -0,0 +1,49 @@ +description: "loadbalanced-emit-topology-description-changed-before-close" + +schemaVersion: "1.20" + +runOnRequirements: + - topologies: + - load-balanced + minServerVersion: "4.4" # awaitable hello + +tests: + - description: "Topology lifecycle" + operations: + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + observeEvents: + - topologyDescriptionChangedEvent + - topologyOpeningEvent + - topologyClosedEvent + # ensure the topology has been fully discovered before closing the client. + # expected events are initial server discovery and server connect event. + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + topologyDescriptionChangedEvent: {} + count: 2 + - name: close + object: *client + expectEvents: + - client: *client + eventType: sdam + events: + - topologyOpeningEvent: {} + - topologyDescriptionChangedEvent: # unknown -> unknown w disconnected server + previousDescription: + type: "Unknown" + newDescription: {} + - topologyDescriptionChangedEvent: # unknown w disconnected server -> loadBalanced + newDescription: + type: "LoadBalanced" + - topologyDescriptionChangedEvent: # loadbalanced -> unknown + newDescription: + type: "Unknown" + - topologyClosedEvent: {} diff --git a/testdata/server-discovery-and-monitoring/unified/logging-loadbalanced.json b/testdata/server-discovery-and-monitoring/unified/logging-loadbalanced.json index 45440d2557..0ad3b0ceaa 100644 --- a/testdata/server-discovery-and-monitoring/unified/logging-loadbalanced.json +++ b/testdata/server-discovery-and-monitoring/unified/logging-loadbalanced.json @@ -132,6 +132,22 @@ } } }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, { "level": "debug", "component": "topology", diff --git a/testdata/server-discovery-and-monitoring/unified/logging-loadbalanced.yml b/testdata/server-discovery-and-monitoring/unified/logging-loadbalanced.yml index 87ad4bcf5d..432ec354ed 100644 --- a/testdata/server-discovery-and-monitoring/unified/logging-loadbalanced.yml +++ b/testdata/server-discovery-and-monitoring/unified/logging-loadbalanced.yml @@ -67,6 +67,13 @@ tests: topologyId: { $$exists: true } serverHost: { $$type: string } serverPort: { $$type: [int, long] } + - level: debug + component: topology + data: + message: "Topology description changed" + topologyId: { $$exists: true } + previousDescription: { $$exists: true } # loadBalanced topology + newDescription: { $$exists: true } # unknown topology - level: debug component: topology data: diff --git a/testdata/server-discovery-and-monitoring/unified/replicaset-emit-topology-changed-before-close.json b/testdata/server-discovery-and-monitoring/unified/replicaset-emit-topology-changed-before-close.json new file mode 100644 index 0000000000..066a4ffee5 --- /dev/null +++ b/testdata/server-discovery-and-monitoring/unified/replicaset-emit-topology-changed-before-close.json @@ -0,0 +1,89 @@ +{ + "description": "replicaset-emit-topology-description-changed-before-close", + "schemaVersion": "1.20", + "runOnRequirements": [ + { + "topologies": [ + "replicaset" + ], + "minServerVersion": "4.4" + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "topologyOpeningEvent", + "topologyClosedEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 4 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": false, + "events": [ + { + "topologyOpeningEvent": {} + }, + { + "topologyDescriptionChangedEvent": {} + }, + { + "topologyDescriptionChangedEvent": {} + }, + { + "topologyDescriptionChangedEvent": {} + }, + { + "topologyDescriptionChangedEvent": {} + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "ReplicaSetWithPrimary" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/testdata/server-discovery-and-monitoring/unified/replicaset-emit-topology-changed-before-close.yml b/testdata/server-discovery-and-monitoring/unified/replicaset-emit-topology-changed-before-close.yml new file mode 100644 index 0000000000..d0a1158ea9 --- /dev/null +++ b/testdata/server-discovery-and-monitoring/unified/replicaset-emit-topology-changed-before-close.yml @@ -0,0 +1,49 @@ +description: "replicaset-emit-topology-description-changed-before-close" + +schemaVersion: "1.20" + +runOnRequirements: + - topologies: + - replicaset + minServerVersion: "4.4" # awaitable hello + +tests: + - description: "Topology lifecycle" + operations: + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + observeEvents: + - topologyDescriptionChangedEvent + - topologyOpeningEvent + - topologyClosedEvent + # ensure the topology has been fully discovered before closing the client. + # expected events are initial server discovery and 3 server connect events. + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + topologyDescriptionChangedEvent: {} + count: 4 + - name: close + object: *client + expectEvents: + - client: *client + eventType: sdam + ignoreExtraEvents: false + events: + - topologyOpeningEvent: {} + - topologyDescriptionChangedEvent: {} # unknown -> replset no primary + - topologyDescriptionChangedEvent: {} # server connected + - topologyDescriptionChangedEvent: {} # server connected + - topologyDescriptionChangedEvent: {} # server connected + - topologyDescriptionChangedEvent: # replicaset -> unknown + previousDescription: + type: "ReplicaSetWithPrimary" + newDescription: + type: "Unknown" + - topologyClosedEvent: {} diff --git a/testdata/server-discovery-and-monitoring/unified/sharded-emit-topology-changed-before-close.json b/testdata/server-discovery-and-monitoring/unified/sharded-emit-topology-changed-before-close.json new file mode 100644 index 0000000000..98fb585531 --- /dev/null +++ b/testdata/server-discovery-and-monitoring/unified/sharded-emit-topology-changed-before-close.json @@ -0,0 +1,108 @@ +{ + "description": "sharded-emit-topology-description-changed-before-close", + "schemaVersion": "1.20", + "runOnRequirements": [ + { + "topologies": [ + "sharded" + ], + "minServerVersion": "4.4" + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "topologyOpeningEvent", + "topologyClosedEvent" + ], + "useMultipleMongoses": true + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 3 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": false, + "events": [ + { + "topologyOpeningEvent": {} + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Sharded" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Sharded" + }, + "newDescription": { + "type": "Sharded" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Sharded" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/testdata/server-discovery-and-monitoring/unified/sharded-emit-topology-changed-before-close.yml b/testdata/server-discovery-and-monitoring/unified/sharded-emit-topology-changed-before-close.yml new file mode 100644 index 0000000000..cb6cc5ad4d --- /dev/null +++ b/testdata/server-discovery-and-monitoring/unified/sharded-emit-topology-changed-before-close.yml @@ -0,0 +1,62 @@ +description: "sharded-emit-topology-description-changed-before-close" + +schemaVersion: "1.20" + +runOnRequirements: + - topologies: + - sharded + minServerVersion: "4.4" # awaitable hello + +tests: + - description: "Topology lifecycle" + operations: + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + observeEvents: + - topologyDescriptionChangedEvent + - topologyOpeningEvent + - topologyClosedEvent + useMultipleMongoses: true + # ensure the topology has been fully discovered before closing the client. + # expected events are initial cluster type change from unknown to sharded and connect events + # for each of 2 servers + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + topologyDescriptionChangedEvent: {} + count: 3 + - name: close + object: *client + expectEvents: + - client: *client + eventType: sdam + ignoreExtraEvents: false + events: + - topologyOpeningEvent: {} + - topologyDescriptionChangedEvent: # unknown -> unknown w disconnected server + previousDescription: + type: "Unknown" + newDescription: + type: "Unknown" + - topologyDescriptionChangedEvent: # server connected + previousDescription: + type: "Unknown" + newDescription: + type: "Sharded" + - topologyDescriptionChangedEvent: # server connected + previousDescription: + type: "Sharded" + newDescription: + type: "Sharded" + - topologyDescriptionChangedEvent: # sharded -> unknown + previousDescription: + type: "Sharded" + newDescription: + type: "Unknown" + - topologyClosedEvent: {} diff --git a/testdata/server-discovery-and-monitoring/unified/standalone-emit-topology-changed-before-close.json b/testdata/server-discovery-and-monitoring/unified/standalone-emit-topology-changed-before-close.json new file mode 100644 index 0000000000..27b5444d54 --- /dev/null +++ b/testdata/server-discovery-and-monitoring/unified/standalone-emit-topology-changed-before-close.json @@ -0,0 +1,97 @@ +{ + "description": "standalone-emit-topology-description-changed-before-close", + "schemaVersion": "1.20", + "runOnRequirements": [ + { + "topologies": [ + "single" + ], + "minServerVersion": "4.4" + } + ], + "tests": [ + { + "description": "Topology lifecycle", + "operations": [ + { + "name": "createEntities", + "object": "testRunner", + "arguments": { + "entities": [ + { + "client": { + "id": "client", + "observeEvents": [ + "topologyDescriptionChangedEvent", + "topologyOpeningEvent", + "topologyClosedEvent" + ] + } + } + ] + } + }, + { + "name": "waitForEvent", + "object": "testRunner", + "arguments": { + "client": "client", + "event": { + "topologyDescriptionChangedEvent": {} + }, + "count": 2 + } + }, + { + "name": "close", + "object": "client" + } + ], + "expectEvents": [ + { + "client": "client", + "eventType": "sdam", + "ignoreExtraEvents": false, + "events": [ + { + "topologyOpeningEvent": {} + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Unknown" + }, + "newDescription": { + "type": "Single" + } + } + }, + { + "topologyDescriptionChangedEvent": { + "previousDescription": { + "type": "Single" + }, + "newDescription": { + "type": "Unknown" + } + } + }, + { + "topologyClosedEvent": {} + } + ] + } + ] + } + ] +} diff --git a/testdata/server-discovery-and-monitoring/unified/standalone-emit-topology-changed-before-close.yml b/testdata/server-discovery-and-monitoring/unified/standalone-emit-topology-changed-before-close.yml new file mode 100644 index 0000000000..20fa380bd5 --- /dev/null +++ b/testdata/server-discovery-and-monitoring/unified/standalone-emit-topology-changed-before-close.yml @@ -0,0 +1,55 @@ +description: "standalone-emit-topology-description-changed-before-close" + +schemaVersion: "1.20" + +runOnRequirements: + - topologies: + - single + minServerVersion: "4.4" # awaitable hello + +tests: + - description: "Topology lifecycle" + operations: + - name: createEntities + object: testRunner + arguments: + entities: + - client: + id: &client client + observeEvents: + - topologyDescriptionChangedEvent + - topologyOpeningEvent + - topologyClosedEvent + # ensure the topology has been fully discovered before closing the client. + # expected events are initial server discovery and server connect event. + - name: waitForEvent + object: testRunner + arguments: + client: *client + event: + topologyDescriptionChangedEvent: {} + count: 2 + - name: close + object: *client + expectEvents: + - client: *client + eventType: sdam + ignoreExtraEvents: false + events: + - topologyOpeningEvent: {} + - topologyDescriptionChangedEvent: # unknown -> unknown w disconnected server + previousDescription: + type: "Unknown" + newDescription: + type: "Unknown" + - topologyDescriptionChangedEvent: # unknown w disconnected server -> standalone + previousDescription: + type: "Unknown" + newDescription: + type: "Single" + - topologyDescriptionChangedEvent: # standalone -> unknown + previousDescription: + type: "Single" + newDescription: + type: "Unknown" + - topologyClosedEvent: {} From 199dbc55fa34876f1f4bb0e267e0a7e47a4753fe Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Fri, 28 Mar 2025 11:02:44 -0400 Subject: [PATCH 2/4] Publish TopologyDescriptionChangedEvent on topology close. --- internal/integration/unified/client_entity.go | 34 +++++++++ internal/integration/unified/event.go | 6 ++ .../integration/unified/event_verification.go | 69 +++++++++++++++++-- x/mongo/driver/topology/topology.go | 5 +- 4 files changed, 107 insertions(+), 7 deletions(-) diff --git a/internal/integration/unified/client_entity.go b/internal/integration/unified/client_entity.go index 08b9fd7866..6d5fedc38c 100644 --- a/internal/integration/unified/client_entity.go +++ b/internal/integration/unified/client_entity.go @@ -54,6 +54,8 @@ type clientEntity struct { serverHeartbeatStartedEvent []*event.ServerHeartbeatStartedEvent serverHeartbeatSucceeded []*event.ServerHeartbeatSucceededEvent topologyDescriptionChanged []*event.TopologyDescriptionChangedEvent + topologyOpening []*event.TopologyOpeningEvent + topologyClosed []*event.TopologyClosedEvent ignoredCommands map[string]struct{} observeSensitiveCommands *bool numConnsCheckedOut int32 @@ -161,6 +163,8 @@ func newClientEntity(ctx context.Context, em *EntityMap, entityOptions *entityOp ServerHeartbeatStarted: entity.processServerHeartbeatStartedEvent, ServerHeartbeatSucceeded: entity.processServerHeartbeatSucceededEvent, TopologyDescriptionChanged: entity.processTopologyDescriptionChangedEvent, + TopologyOpening: entity.processTopologyOpeningEvent, + TopologyClosed: entity.processTopologyClosedEvent, } clientOpts.SetMonitor(commandMonitor).SetPoolMonitor(poolMonitor).SetServerMonitor(serverMonitor) @@ -575,6 +579,36 @@ func (c *clientEntity) processTopologyDescriptionChangedEvent(evt *event.Topolog c.addEventsCount(topologyDescriptionChangedEvent) } +func (c *clientEntity) processTopologyOpeningEvent(evt *event.TopologyOpeningEvent) { + c.eventProcessMu.Lock() + defer c.eventProcessMu.Unlock() + + if !c.getRecordEvents() { + return + } + + if _, ok := c.observedEvents[topologyOpeningEvent]; ok { + c.topologyOpening = append(c.topologyOpening, evt) + } + + c.addEventsCount(topologyOpeningEvent) +} + +func (c *clientEntity) processTopologyClosedEvent(evt *event.TopologyClosedEvent) { + c.eventProcessMu.Lock() + defer c.eventProcessMu.Unlock() + + if !c.getRecordEvents() { + return + } + + if _, ok := c.observedEvents[topologyClosedEvent]; ok { + c.topologyClosed = append(c.topologyClosed, evt) + } + + c.addEventsCount(topologyClosedEvent) +} + func (c *clientEntity) setRecordEvents(record bool) { c.recordEvents.Store(record) } diff --git a/internal/integration/unified/event.go b/internal/integration/unified/event.go index 9e6d6d5a35..abbec74439 100644 --- a/internal/integration/unified/event.go +++ b/internal/integration/unified/event.go @@ -35,6 +35,8 @@ const ( serverHeartbeatStartedEvent monitoringEventType = "ServerHeartbeatStartedEvent" serverHeartbeatSucceededEvent monitoringEventType = "ServerHeartbeatSucceededEvent" topologyDescriptionChangedEvent monitoringEventType = "TopologyDescriptionChangedEvent" + topologyOpeningEvent monitoringEventType = "TopologyOpeningEvent" + topologyClosedEvent monitoringEventType = "TopologyClosedEvent" ) func monitoringEventTypeFromString(eventStr string) (monitoringEventType, bool) { @@ -77,6 +79,10 @@ func monitoringEventTypeFromString(eventStr string) (monitoringEventType, bool) return serverHeartbeatSucceededEvent, true case "topologydescriptionchangedevent": return topologyDescriptionChangedEvent, true + case "topologyopeningevent": + return topologyOpeningEvent, true + case "topologyclosedevent": + return topologyClosedEvent, true default: return "", false } diff --git a/internal/integration/unified/event_verification.go b/internal/integration/unified/event_verification.go index ebdb0b19c3..e90e47a9e2 100644 --- a/internal/integration/unified/event_verification.go +++ b/internal/integration/unified/event_verification.go @@ -87,7 +87,16 @@ type sdamEvent struct { Awaited *bool `bson:"awaited"` } `bson:"serverHeartbeatFailedEvent"` - TopologyDescriptionChangedEvent *struct{} `bson:"topologyDescriptionChangedEvent"` + TopologyDescriptionChangedEvent *struct { + PreviousDescription *struct { + Type string `bson:"type"` + } `bson:"previousDescription"` + NewDescription *struct { + Type string `bson:"type"` + } `bson:"newDescription"` + } `bson:"topologyDescriptionChangedEvent"` + TopologyOpeningEvent *struct{} `bson:"topologyOpeningEvent"` + TopologyClosedEvent *struct{} `bson:"topologyClosedEvent"` } type expectedEvents struct { @@ -468,7 +477,7 @@ func getNextServerHeartbeatSucceededEvent( return nil, nil, errors.New("no heartbeat succeeded event published") } - return events[0], events[:1], nil + return events[0], events[1:], nil } func getNextServerHeartbeatFailedEvent( @@ -478,7 +487,7 @@ func getNextServerHeartbeatFailedEvent( return nil, nil, errors.New("no heartbeat failed event published") } - return events[0], events[:1], nil + return events[0], events[1:], nil } func getNextTopologyDescriptionChangedEvent( @@ -488,7 +497,27 @@ func getNextTopologyDescriptionChangedEvent( return nil, nil, errors.New("no topology description changed event published") } - return events[0], events[:1], nil + return events[0], events[1:], nil +} + +func getNextTopologyOpeningEvent( + events []*event.TopologyOpeningEvent, +) (*event.TopologyOpeningEvent, []*event.TopologyOpeningEvent, error) { + if len(events) == 0 { + return nil, nil, errors.New("no topology opening event published") + } + + return events[0], events[1:], nil +} + +func getNextTopologyClosedEvent( + events []*event.TopologyClosedEvent, +) (*event.TopologyClosedEvent, []*event.TopologyClosedEvent, error) { + if len(events) == 0 { + return nil, nil, errors.New("no topology closed event published") + } + + return events[0], events[1:], nil } func verifySDAMEvents(client *clientEntity, expectedEvents *expectedEvents) error { @@ -498,9 +527,21 @@ func verifySDAMEvents(client *clientEntity, expectedEvents *expectedEvents) erro succeeded = client.serverHeartbeatSucceeded failed = client.serverHeartbeatFailedEvent tchanged = client.topologyDescriptionChanged + topening = client.topologyOpening + tclosed = client.topologyClosed ) - vol := func() int { return len(changed) + len(started) + len(succeeded) + len(failed) + len(tchanged) } + vol := func() int { + var count int + count += len(changed) + count += len(started) + count += len(succeeded) + count += len(failed) + count += len(tchanged) + count += len(topening) + count += len(tclosed) + return count + } if len(expectedEvents.SDAMEvents) == 0 && vol() != 0 { return fmt.Errorf("expected no sdam events to be sent but got %s", stringifyEventsForClient(client)) @@ -569,7 +610,23 @@ func verifySDAMEvents(client *clientEntity, expectedEvents *expectedEvents) erro return newEventVerificationError(idx, client, "want awaited %v, got %v", *want, got.Awaited) } case evt.TopologyDescriptionChangedEvent != nil: - if _, tchanged, err = getNextTopologyDescriptionChangedEvent(tchanged); err != nil { + var got *event.TopologyDescriptionChangedEvent + if got, tchanged, err = getNextTopologyDescriptionChangedEvent(tchanged); err != nil { + return newEventVerificationError(idx, client, "failed to get next description changed event: %v", err.Error()) + } + + if want := evt.TopologyDescriptionChangedEvent.PreviousDescription; want != nil && want.Type != got.PreviousDescription.Kind { + return newEventVerificationError(idx, client, "want previous description %v, got %v", want.Type, got.PreviousDescription.Kind) + } + if want := evt.TopologyDescriptionChangedEvent.NewDescription; want != nil && want.Type != got.NewDescription.Kind { + return newEventVerificationError(idx, client, "want new description %v, got %v", want.Type, got.NewDescription.Kind) + } + case evt.TopologyOpeningEvent != nil: + if _, topening, err = getNextTopologyOpeningEvent(topening); err != nil { + return newEventVerificationError(idx, client, "failed to get next description changed event: %v", err.Error()) + } + case evt.TopologyClosedEvent != nil: + if _, tclosed, err = getNextTopologyClosedEvent(tclosed); err != nil { return newEventVerificationError(idx, client, "failed to get next description changed event: %v", err.Error()) } } diff --git a/x/mongo/driver/topology/topology.go b/x/mongo/driver/topology/topology.go index 5c1e1342da..ccb154b9e9 100644 --- a/x/mongo/driver/topology/topology.go +++ b/x/mongo/driver/topology/topology.go @@ -405,7 +405,10 @@ func (t *Topology) Disconnect(ctx context.Context) error { t.pollingwg.Wait() } - t.desc.Store(description.Topology{}) + oldDesc := t.fsm.Topology + t.fsm = newFSM() + t.desc.Store(t.fsm.Topology) + t.publishTopologyDescriptionChangedEvent(oldDesc, t.fsm.Topology) atomic.StoreInt64(&t.state, topologyDisconnected) t.publishTopologyClosedEvent() From 2e5069c259428d0d718a7ae06801389f00ed7a89 Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Fri, 28 Mar 2025 14:24:52 -0400 Subject: [PATCH 3/4] Sync up SDAM logging test case. --- .../unified/logging-replicaset.json | 16 ++++++++++++++++ .../unified/logging-replicaset.yml | 7 ------- .../unified/logging-sharded.json | 16 ++++++++++++++++ .../unified/logging-sharded.yml | 7 ------- .../unified/logging-standalone.json | 16 ++++++++++++++++ .../unified/logging-standalone.yml | 7 ------- 6 files changed, 48 insertions(+), 21 deletions(-) diff --git a/testdata/server-discovery-and-monitoring/unified/logging-replicaset.json b/testdata/server-discovery-and-monitoring/unified/logging-replicaset.json index 8522c14e19..e6738225cd 100644 --- a/testdata/server-discovery-and-monitoring/unified/logging-replicaset.json +++ b/testdata/server-discovery-and-monitoring/unified/logging-replicaset.json @@ -220,6 +220,22 @@ } } }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, { "level": "debug", "component": "topology", diff --git a/testdata/server-discovery-and-monitoring/unified/logging-replicaset.yml b/testdata/server-discovery-and-monitoring/unified/logging-replicaset.yml index 176c4e5e18..4644dc1355 100644 --- a/testdata/server-discovery-and-monitoring/unified/logging-replicaset.yml +++ b/testdata/server-discovery-and-monitoring/unified/logging-replicaset.yml @@ -109,13 +109,6 @@ tests: topologyId: { $$exists: true } serverHost: { $$type: string } serverPort: { $$type: [int, long] } - # TODO(GODRIVER-2967): The following log message has been removed from - # the JSON analogue because it assumes that - # "TopologyDescriptionChangedEvent" should occur when a topolgoy is - # closed. This behavior is not clearly defined anywhere and some - # drivers support and some don't. - # - # Need to sync whenever GODRIVER-2967 is unblocked. - level: debug component: topology data: diff --git a/testdata/server-discovery-and-monitoring/unified/logging-sharded.json b/testdata/server-discovery-and-monitoring/unified/logging-sharded.json index 33e7ec4bfe..61b27f5be0 100644 --- a/testdata/server-discovery-and-monitoring/unified/logging-sharded.json +++ b/testdata/server-discovery-and-monitoring/unified/logging-sharded.json @@ -187,6 +187,22 @@ } } }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, { "level": "debug", "component": "topology", diff --git a/testdata/server-discovery-and-monitoring/unified/logging-sharded.yml b/testdata/server-discovery-and-monitoring/unified/logging-sharded.yml index f175ce0f90..34cd3611e2 100644 --- a/testdata/server-discovery-and-monitoring/unified/logging-sharded.yml +++ b/testdata/server-discovery-and-monitoring/unified/logging-sharded.yml @@ -97,13 +97,6 @@ tests: topologyId: { $$exists: true } serverHost: { $$type: string } serverPort: { $$type: [int, long] } - # TODO(GODRIVER-2967): The following log message has been removed from - # the JSON analogue because it assumes that - # "TopologyDescriptionChangedEvent" should occur when a topolgoy is - # closed. This behavior is not clearly defined anywhere and some - # drivers support and some don't. - # - # Need to sync whenever GODRIVER-2967 is unblocked. - level: debug component: topology data: diff --git a/testdata/server-discovery-and-monitoring/unified/logging-standalone.json b/testdata/server-discovery-and-monitoring/unified/logging-standalone.json index f27d651afc..1ee6dbe899 100644 --- a/testdata/server-discovery-and-monitoring/unified/logging-standalone.json +++ b/testdata/server-discovery-and-monitoring/unified/logging-standalone.json @@ -162,6 +162,22 @@ } } }, + { + "level": "debug", + "component": "topology", + "data": { + "message": "Topology description changed", + "topologyId": { + "$$exists": true + }, + "previousDescription": { + "$$exists": true + }, + "newDescription": { + "$$exists": true + } + } + }, { "level": "debug", "component": "topology", diff --git a/testdata/server-discovery-and-monitoring/unified/logging-standalone.yml b/testdata/server-discovery-and-monitoring/unified/logging-standalone.yml index 0b378cd2fc..95c2676d44 100644 --- a/testdata/server-discovery-and-monitoring/unified/logging-standalone.yml +++ b/testdata/server-discovery-and-monitoring/unified/logging-standalone.yml @@ -84,13 +84,6 @@ tests: topologyId: { $$exists: true } serverHost: { $$type: string } serverPort: { $$type: [int, long] } - # TODO(GODRIVER-2967): The following log message has been removed from - # the JSON analogue because it assumes that - # "TopologyDescriptionChangedEvent" should occur when a topolgoy is - # closed. This behavior is not clearly defined anywhere and some - # drivers support and some don't. - # - # Need to sync whenever GODRIVER-2967 is unblocked. - level: debug component: topology data: From db8feb3e519e7a59cbc7acfdef6766728fe68e7c Mon Sep 17 00:00:00 2001 From: Qingyang Hu Date: Fri, 28 Mar 2025 14:48:00 -0400 Subject: [PATCH 4/4] update for optional type --- internal/integration/unified/event_verification.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/integration/unified/event_verification.go b/internal/integration/unified/event_verification.go index e90e47a9e2..56c53f8adb 100644 --- a/internal/integration/unified/event_verification.go +++ b/internal/integration/unified/event_verification.go @@ -89,10 +89,10 @@ type sdamEvent struct { TopologyDescriptionChangedEvent *struct { PreviousDescription *struct { - Type string `bson:"type"` + Type *string `bson:"type"` } `bson:"previousDescription"` NewDescription *struct { - Type string `bson:"type"` + Type *string `bson:"type"` } `bson:"newDescription"` } `bson:"topologyDescriptionChangedEvent"` TopologyOpeningEvent *struct{} `bson:"topologyOpeningEvent"` @@ -615,11 +615,11 @@ func verifySDAMEvents(client *clientEntity, expectedEvents *expectedEvents) erro return newEventVerificationError(idx, client, "failed to get next description changed event: %v", err.Error()) } - if want := evt.TopologyDescriptionChangedEvent.PreviousDescription; want != nil && want.Type != got.PreviousDescription.Kind { - return newEventVerificationError(idx, client, "want previous description %v, got %v", want.Type, got.PreviousDescription.Kind) + if want := evt.TopologyDescriptionChangedEvent.PreviousDescription; want != nil && want.Type != nil && *want.Type != got.PreviousDescription.Kind { + return newEventVerificationError(idx, client, "want previous description %v, got %v", *want.Type, got.PreviousDescription.Kind) } - if want := evt.TopologyDescriptionChangedEvent.NewDescription; want != nil && want.Type != got.NewDescription.Kind { - return newEventVerificationError(idx, client, "want new description %v, got %v", want.Type, got.NewDescription.Kind) + if want := evt.TopologyDescriptionChangedEvent.NewDescription; want != nil && want.Type != nil && *want.Type != got.NewDescription.Kind { + return newEventVerificationError(idx, client, "want new description %v, got %v", *want.Type, got.NewDescription.Kind) } case evt.TopologyOpeningEvent != nil: if _, topening, err = getNextTopologyOpeningEvent(topening); err != nil {