Skip to content

Conversation

@bbotella
Copy link
Contributor

@bbotella bbotella commented Dec 1, 2025

Patch by James Berragan, Jyothsna Konisa, Bernardo Botella; reviewed by for CASSSIDECAR-243

Copy link
Contributor

@jyothsnakonisa jyothsnakonisa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good overall, leaving some comments.

}

@Test
void testConfigChanged() throws Exception
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you remove this test? I think this is valuable to have a test for checking callback and config updating when config is changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This became a periodic task, and the callback was moved to a vertx signal instead.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I think the test is sill valid right? may be we should have the test to check if the vertx signal is made when config is changed

@jyothsnakonisa
Copy link
Contributor

Thanks @bbotella for addressing my comments. There is this comment #294 (comment) which is not resolved. We need to look into that codepath as it is critical for leader election and mutation publishing.

Also, can you please check if there is a way to add an end to end test that checks if the mutations are published(in-memory) might not need to have kafka for the test.

Other than those two everything else looks good to me.

Copy link
Contributor

@jyothsnakonisa jyothsnakonisa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Bernardo for the patch!

@bbotella bbotella force-pushed the CASSSIDECAR-243-CDCPublisher branch from 73efd40 to b594d40 Compare December 19, 2025 18:22
*/
public BigInteger decodeFromWire(int pos, Buffer buf)
{
return decodeFromWire(new MutableInt(pos), buf);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the MutableInt is only required if we need to track the change in position in a wrapper serializer, this would be marginally faster as:

Suggested change
return decodeFromWire(new MutableInt(pos), buf);
return new BigInteger(CommonCodecs.BYTE_ARRAY.decodeFromWire(pos, buf));

private volatile Map<String, String> kafkaConfigMappings = Map.of();
private volatile Map<String, String> cdcConfigMappings = Map.of();

private Map<String, String> kafkaConfigMappings = Map.of();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These look like they should be volatile

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There not accessed with synchronized so better to make them volatile

}
});
}))
.collect(Collectors.toList());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Result of .collect(Collectors.toList()); is ignored/not used.

}

// NEW: Deduplicate by (instanceId, tokenRange) to prevent duplicate consumers
Map<String, SidecarCdc> uniqueConsumers = new HashMap<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Map<String, SidecarCdc> uniqueConsumers = new HashMap<>();
Map<String, SidecarCdc> uniqueConsumers = new HashMap<>(ownedRanges.values().stream().mapToInt(Set::size).sum());

return -1;
}

private boolean resolveToSameAddress(String host1, String host2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this only expects ip addresses to be input, and so will not perform DNS resolution. Can we make that explicit? We can also make the method static and add some unit tests here.

{
for (InstanceMetadata instance : instanceFetcher.allLocalInstances())
{
String configuredHost = instance.ipAddress();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an ip address, no?

Suggested change
String configuredHost = instance.ipAddress();
String configuredIpAddress = instance.ipAddress();

private final ICdcStats cdcStats;
private final SidecarConfiguration sidecarConfiguration;
private CdcManager cdcManager;
private Serializer<CdcEvent> avroSerializer;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be final:

Suggested change
private Serializer<CdcEvent> avroSerializer;
private final Serializer<CdcEvent> avroSerializer;
private final Provider<RangeManager> rangeManagerProvider;

Copy link
Contributor

@jberragan jberragan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly nits, +1 (nb)

@bbotella bbotella force-pushed the CASSSIDECAR-243-CDCPublisher branch from 87d98d5 to 363a547 Compare January 7, 2026 16:37
Copy link
Contributor

@yifan-c yifan-c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When CDC is disabled,

Comment on lines 174 to 175
loadPublisher();
publishSchemas();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those 2 methods are called in every iteration. Looks like they are included in the for-loop by mistake.

private void loadPublisher()
{
KafkaOptions kafkaOptions = () -> cdcConfig.kafkaConfigs();
this.publisher = SchemaStorePublisherFactory.DEFAULT.buildPublisher(kafkaOptions);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

publisher is a Closeable object. We should close the previous object when assigning a new one.

}
});
}))
.collect(Collectors.toList());;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

double ;

Comment on lines 117 to 133
ON_CDC_CONFIGURATION_CHANGED,
ON_CDC_CACHE_WARMED_UP,
ON_CDC_CONFIG_MAPPINGS_CHANGED,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add javadoc

Comment on lines 417 to 418
KafkaConfigAccessor kafkaConfigAccessor,
CdcConfigAccessor cdcConfigAccessor)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indentation

SidecarSchema sidecarSchema,
CqlToAvroSchemaConverter cqlToAvroSchemaConverter)
{
super();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super() is redundant, because it is just implementing the interface SchemaStore

Comment on lines 93 to 100
this.avroSchemasCache.putAll(createSchemaCache(cassandraClusterSchemaMonitor.getCdcTables()));
AvroSchemas.registerLogicalTypes();
cassandraClusterSchemaMonitor.addSchemaChangeListener(this::onSchemaChanged);
this.vertx = vertx;
this.cdcConfig = cdcConfig;
this.sidecarCdcStats = sidecarCdcStats;

configureSidecarServerEventListeners();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When CDC is disabled, we should skip those all together. It does not make sense to register listeners, etc.

Ideally, we should not mount the CdcModule entirely, if the feature is not enabled. It is outside of the scope of this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will create a Jira

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. Just to clarify that conditionally register the listeners are still wanted in this patch.

Comment on lines 143 to 148
vertx.eventBus().localConsumer(RangeManager.RangeManagerEvents.ON_TOKEN_RANGE_CHANGED.address(), this);
vertx.eventBus().localConsumer(RangeManager.LeadershipEvents.ON_TOKEN_RANGE_GAINED.address(), this);
vertx.eventBus().localConsumer(RangeManager.LeadershipEvents.ON_TOKEN_RANGE_LOST.address(), this);
vertx.eventBus().localConsumer(ON_SERVER_STOP.address(), this);
vertx.eventBus().localConsumer(ON_CDC_CACHE_WARMED_UP.address(), this);
vertx.eventBus().localConsumer(ON_CDC_CONFIGURATION_CHANGED.address(), new ConfigChangedHandler());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skip those when CDC is disabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be part of the Jira mentioned in previous comment?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those should be behind the condition whether cdc is enabled.

Comment on lines 192 to 193
KafkaProducer<String, byte[]> producer = new KafkaProducer<>(conf.kafkaConfigs());
KafkaPublisher kafkaPublisher = new KafkaPublisher(TopicSupplier.staticTopicSupplier(conf.kafkaTopic()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both producer and kafkaPublisher are Closeable. I do not see them get closed anywhere. We are create a new eventConsumer on every publisher restart, meaning leaks.

@bbotella bbotella force-pushed the CASSSIDECAR-243-CDCPublisher branch from 5825499 to 8c25504 Compare January 9, 2026 21:09
@bbotella bbotella merged commit 1ee13fb into apache:trunk Jan 9, 2026
29 of 30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants