@@ -214,16 +214,24 @@ private void maybeSample(
214214 return ;
215215 }
216216 long startTime = statsTimeSupplier .getAsLong ();
217- SamplingConfiguration samplingConfig = getSamplingConfiguration (projectMetadata , indexName );
218- if (samplingConfig == null ) {
219- return ;
220- }
221- SoftReference <SampleInfo > sampleInfoReference = samples .compute (
222- new ProjectIndex (projectMetadata .id (), indexName ),
223- (k , v ) -> v == null || v .get () == null ? new SoftReference <>(new SampleInfo (samplingConfig .maxSamples ())) : v
224- );
217+ SoftReference <SampleInfo > sampleInfoReference = samples .compute (new ProjectIndex (projectMetadata .id (), indexName ), (k , v ) -> {
218+ if (v == null || v .get () == null ) {
219+ SamplingConfiguration samplingConfig = getSamplingConfiguration (projectMetadata , indexName );
220+ if (samplingConfig == null ) {
221+ /*
222+ * Calls to getSamplingConfiguration() are relatively expensive. So we store the NONE object here to indicate that there
223+ * was no sampling configuration. This way we don't have to do the lookup every single time for every index that has no
224+ * sampling configuration. If a sampling configuration is added for this index, this NONE sample will be removed by
225+ * the cluster state change listener.
226+ */
227+ return new SoftReference <>(SampleInfo .NONE );
228+ }
229+ return new SoftReference <>(new SampleInfo (samplingConfig .maxSamples ()));
230+ }
231+ return v ;
232+ });
225233 SampleInfo sampleInfo = sampleInfoReference .get ();
226- if (sampleInfo == null ) {
234+ if (sampleInfo == null || sampleInfo == SampleInfo . NONE ) {
227235 return ;
228236 }
229237 SampleStats stats = sampleInfo .stats ;
@@ -233,6 +241,10 @@ private void maybeSample(
233241 stats .samplesRejectedForMaxSamplesExceeded .increment ();
234242 return ;
235243 }
244+ SamplingConfiguration samplingConfig = getSamplingConfiguration (projectMetadata , indexName );
245+ if (samplingConfig == null ) {
246+ return ; // it was not null above, but has since become null because the index was deleted asynchronously
247+ }
236248 if (sampleInfo .getSizeInBytes () + indexRequest .source ().length () > samplingConfig .maxSize ().getBytes ()) {
237249 stats .samplesRejectedForSize .increment ();
238250 return ;
@@ -496,7 +508,12 @@ private void maybeRemoveStaleSamples(ClusterChangedEvent event, ProjectId projec
496508 if (oldSampleConfigsMap .containsKey (indexName ) && entry .getValue ().equals (oldSampleConfigsMap .get (indexName )) == false ) {
497509 logger .debug ("Removing sample info for {} because its configuration has changed" , indexName );
498510 samples .remove (new ProjectIndex (projectId , indexName ));
499- }
511+ } else if (oldSampleConfigsMap .containsKey (indexName ) == false
512+ && samples .containsKey (new ProjectIndex (projectId , indexName ))) {
513+ // There had previously been a NONE sample here. There is a real config now, so delete the NONE sample
514+ logger .debug ("Removing sample info for {} because its configuration has been created" , indexName );
515+ samples .remove (new ProjectIndex (projectId , indexName ));
516+ }
500517 }
501518 }
502519 }
@@ -1040,6 +1057,7 @@ public SampleStats adjustForMaxSize(int maxSize) {
10401057 * This is used internally to store information about a sample in the samples Map.
10411058 */
10421059 private static final class SampleInfo {
1060+ public static final SampleInfo NONE = new SampleInfo (0 );
10431061 private final RawDocument [] rawDocuments ;
10441062 /*
10451063 * This stores the maximum index in rawDocuments that has data currently. This is incremented speculatively before writing data to
0 commit comments