My WebSocketStompClient created with default heart-beat (10000,10000). But without activity it can send ping sometimes with 15 seconds +- N ms. So stomp server just disconnected me after 15 sec without pings

The problem in this code

public void onWriteInactivity(final Runnable runnable, final long duration) {
    Assert.state(getTaskScheduler() != null, "No TaskScheduler configured");
    this.lastWriteTime = System.currentTimeMillis();
    this.inactivityTasks.add(getTaskScheduler().scheduleWithFixedDelay(() -> {
        if (System.currentTimeMillis() - this.lastWriteTime > duration) {
            try {
                runnable.run();
            }
            catch (Throwable ex) {
                if (logger.isDebugEnabled()) {
                    logger.debug("WriteInactivityTask failure", ex);
                }
            }
        }
    }, duration / 2));
}

It rechecks inactivity with half-period... So client can exceed even 15 sec recheck period + network time.

It's far enough from target 10 sec Specification part: https://stomp.github.io/stomp-specification-1.2.html#Heart-beating

the sender MUST send new data over the network connection at least every < n > milliseconds

Comment From: rstoyanchev

A heartbeat is sent after 5 sec, and the server hasn't seen it after 10 more seconds. Given a a 10 sec timeout even if we checked 1-2 seconds earlier it might not be enough to help, and if the network is quicker, then we'd be sending heartbeats too frequently.

I've seen recommendations for servers to be tolerant and use a multiplier of 3 times the configured interval read inactivity before closing the connection. Not sure which server you have but given a timeout of 10 sec, closing at 15 is quite aggressive. Alternatively, you might have to increase the timeout period.

Comment From: trovio-dev

Doesn't the > duration guarantee that it will never send a heartbeat within the prescribed duration, irrespective of the timer? Although most servers can be configured to apply a grace period or even deal with a completely missed heartbeat, it would be nice if the implementation at least tries to send a heartbeat within the required maximum idle time.