Skip to content

Cassandra's pool duration mapping uses a wrong duration unit #23249

@littleatp

Description

@littleatp

I use the spring-boot-data-cassandra to connect to my cassandra cluster.
my application configuration is so:

spring.data.cassandra.pool.heartbeat-interval=30s

as above, I set the heartbeat-interval to 30 seconds.
but after application started, I cann't see any debug information about heartbeat actions by datastax driver.
my log4j configuration was set to :

 <Logger name="org.springframework.data.cassandra" level="debug" additivity="true">
        </Logger>
        <Logger name="com.datastax" level="debug" additivity="true">
</Logger>

Then I turn on the code, found it may be a bug by CassandraAutoConfiguration, the snippets as so:

private void mapPoolingOptions(CassandraProperties properties, CassandraDriverOptions options) {
		PropertyMapper map = PropertyMapper.get();
		CassandraProperties.Pool poolProperties = properties.getPool();
		map.from(poolProperties::getIdleTimeout).whenNonNull().asInt(Duration::getSeconds)
				.to((idleTimeout) -> options.add(DefaultDriverOption.HEARTBEAT_TIMEOUT, idleTimeout));
		map.from(poolProperties::getHeartbeatInterval).whenNonNull().asInt(Duration::getSeconds)
				.to((heartBeatInterval) -> options.add(DefaultDriverOption.HEARTBEAT_INTERVAL, heartBeatInterval));
	}

as above, it set DefaultDriverOption.HEARTBEAT_INTERVAL to an integer value(seconds),but datastax driver treat it as mills default, just like this:
com.typesafe.config.impl.SimpleConfig.java

    public static long parseDuration(String input,
            ConfigOrigin originForException, String pathForException) {
        String s = ConfigImplUtil.unicodeTrim(input);
        String originalUnitString = getUnits(s);
        String unitString = originalUnitString;
        String numberString = ConfigImplUtil.unicodeTrim(s.substring(0, s.length()
                - unitString.length()));
        TimeUnit units = null;

        // this would be caught later anyway, but the error message
        // is more helpful if we check it here.
        if (numberString.length() == 0)
            throw new ConfigException.BadValue(originForException,
                    pathForException, "No number in duration value '" + input
                            + "'");

        if (unitString.length() > 2 && !unitString.endsWith("s"))
            unitString = unitString + "s";

        // note that this is deliberately case-sensitive
        if (unitString.equals("") || unitString.equals("ms") || unitString.equals("millis")
                || unitString.equals("milliseconds")) {
            units = TimeUnit.MILLISECONDS;

so, because 30 millis was too short, and HeartbeatHandler cast it to 0 seconds
com.datastax.oss.driver.internal.core.channel.HeartbeatHandler:

  HeartbeatHandler(DriverExecutionProfile config) {
    super((int) config.getDuration(DefaultDriverOption.HEARTBEAT_INTERVAL).getSeconds(), 0, 0);
    this.config = config;
  }

so, there may be some thing to change about CassandraAutoConfiguration ?

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions