<h3 dir="auto">Affected Version</h3>
<p dir="auto">0.22.2 (suspected code path remains unchanged in druid 23 and master)</p>
<h3 dir="auto">Description</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="2022-08-30T14:10:38,628 INFO [HttpServerInventoryView-6] org.apache.druid.server.coordination.ChangeRequestHttpSyncer - [https://XXXXXX.XXXXXX.com:8283/_1661264760506] requested resetCounter for reason [counter[Counter{counter=94953, hash=1661868638606}] &gt;= last counter[Counter{counter=94953, hash=1661868638606}]]."><pre class="notranslate"><code class="notranslate">2022-08-30T14:10:38,628 INFO [HttpServerInventoryView-6] org.apache.druid.server.coordination.ChangeRequestHttpSyncer - [https://XXXXXX.XXXXXX.com:8283/_1661264760506] requested resetCounter for reason [counter[Counter{counter=94953, hash=1661868638606}] &gt;= last counter[Counter{counter=94953, hash=1661868638606}]].
</code></pre></div>
<p dir="auto">You can see here that the client request for changes on this historical provides a Counter that matches the last counter on the server. This causes the client to send a fresh request to the server with a null counter in order to get the full set of segments. I am struggling to understand why we would want to reset a server that is up to date.</p>
<p dir="auto">It looks like <a href="https://github.com/apache/druid/blob/0.22.2/server/src/main/java/org/apache/druid/server/coordination/ChangeRequestHistory.java#L146">this</a> is what is causing the Counter to be reset.</p>
<p dir="auto">It seems that the above code path is run either when the Counter <strong>does not match</strong> when the client request is made OR when the waiting futures (requests waiting for a new change) are resolved <a href="https://github.com/apache/druid/blob/0.22.2/server/src/main/java/org/apache/druid/server/coordination/ChangeRequestHistory.java#L197">here</a>. It is this latter case that I don't understand the reset Counter return to client? Why not send some empty response and the client comes back with the same counter looking for a new change? Resetting it feels like overkill and added work for no gain. Perhaps I'm missing something here, but as of now it feels like incorrect, albeit not destructive, behavior.</p>
<p dir="auto">spit balling on change to <a href="https://github.com/apache/druid/blob/0.22.2/server/src/main/java/org/apache/druid/server/coordination/ChangeRequestHistory.java#L146">the code that controls resetting the Counter</a></p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="    if (counter.counter == lastCounter.counter) {
      if (counter.matches(lastCounter)) {
        // return some empty response that does not cause client to reset counter
      } else {
        // this is bad, fail with a reset due to an incorrect hash - unlikely this would happen here, but it adds safety
      }
    } else if (counter.counter &gt; lastCounter.counter) { // This is modification of original conditional to just GT
      return ChangeRequestsSnapshot.fail(
          StringUtils.format(
              &quot;counter[%s] &gt; last counter[%s]&quot;,
              counter,
              lastCounter
          )
      );
    } else if ..."><pre class="notranslate">    <span class="pl-k">if</span> (<span class="pl-s1">counter</span>.<span class="pl-s1">counter</span> == <span class="pl-s1">lastCounter</span>.<span class="pl-s1">counter</span>) {
      <span class="pl-k">if</span> (<span class="pl-s1">counter</span>.<span class="pl-en">matches</span>(<span class="pl-s1">lastCounter</span>)) {
        <span class="pl-c">// return some empty response that does not cause client to reset counter</span>
      } <span class="pl-k">else</span> {
        <span class="pl-c">// this is bad, fail with a reset due to an incorrect hash - unlikely this would happen here, but it adds safety</span>
      }
    } <span class="pl-k">else</span> <span class="pl-k">if</span> (<span class="pl-s1">counter</span>.<span class="pl-s1">counter</span> &gt; <span class="pl-s1">lastCounter</span>.<span class="pl-s1">counter</span>) { <span class="pl-c">// This is modification of original conditional to just GT</span>
      <span class="pl-k">return</span> <span class="pl-smi">ChangeRequestsSnapshot</span>.<span class="pl-en">fail</span>(
          <span class="pl-smi">StringUtils</span>.<span class="pl-en">format</span>(
              <span class="pl-s">"counter[%s] &gt; last counter[%s]"</span>,
              <span class="pl-s1">counter</span>,
              <span class="pl-s1">lastCounter</span>
          )
      );
    } <span class="pl-k">else</span> <span class="pl-k">if</span> ...</pre></div>
<p dir="auto">Hi all,</p>
<p dir="auto">We're using a count aggregator in most of our data sources, once in a while we get a request to migrate a set of events from some external system. We get these events aggregated, so that a single row represents multiple events.<br>
In order to get the correct count metric, I was thinking about one of -</p>
<ol dir="auto">
<li>Generate duplicate input rows according to the aggregated count - naturally this would be a huge overhead for large number of events</li>
<li>Avoid using count aggregator in general - always use longSum instead, and make sure to send "count": 1 in all our regular/non-migrated events</li>
<li>I think it would be great (maybe there already is such a feature? :) ) to have the ability to configure <code class="notranslate">fieldName</code> on the <code class="notranslate">count</code> aggregator - so that -<br>
a. If fieldName exists in the event JSON, its value will be used<br>
b. Otherwise, the value will be assumed to be 1 (as count normally behaves)</li>
</ol>
<p dir="auto">Thanks!</p>
<p dir="auto">Eran</p>