Skip to content
This repository was archived by the owner on Nov 7, 2025. It is now read-only.

Commit 1d982f4

Browse files
authored
Preserve order of targets in QueryTarget, IngestTarget (#897)
A user in the configuration of a query/ingest processor can define targets: ```yaml my_index: target: [ elastic-conn, clickhouse-conn ] ``` We subsequently take those values and populate `QueryTarget` and `IngestTarget` arrays based on it, however the code did not preserve the order of the targets. The order is important for A/B testing case and `rules.go` had to incorrectly allow an unsupported scenario for everything to work correctly. Fix the issue by preserving the same order in `QueryTarget`, `IngestTarget` as in the original `target` user configuration. `rules.go` workaround can be now removed.
1 parent c8d579e commit 1d982f4

File tree

2 files changed

+36
-31
lines changed

2 files changed

+36
-31
lines changed

quesma/quesma/config/config_v2.go

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,21 @@ func (c *QuesmaNewConfiguration) getProcessorByName(name string) *Processor {
458458
return nil
459459
}
460460

461+
func (c *QuesmaNewConfiguration) getTargetType(backendConnectorName string) (string, bool) {
462+
backendConnector := c.getBackendConnectorByName(backendConnectorName)
463+
if backendConnector == nil {
464+
return "", false
465+
}
466+
switch backendConnector.Type {
467+
case ElasticsearchBackendConnectorName:
468+
return ElasticsearchTarget, true
469+
case ClickHouseOSBackendConnectorName, ClickHouseBackendConnectorName, HydrolixBackendConnectorName:
470+
return ClickhouseTarget, true
471+
default:
472+
return "", false
473+
}
474+
}
475+
461476
func (c *QuesmaNewConfiguration) TranslateToLegacyConfig() QuesmaConfiguration {
462477
var err, errAcc error
463478
var conf QuesmaConfiguration
@@ -505,25 +520,20 @@ func (c *QuesmaNewConfiguration) TranslateToLegacyConfig() QuesmaConfiguration {
505520
// this a COPY-PASTE from the dual pipeline case, but we need to do it here as well
506521
// TODO refactor this to a separate function
507522

508-
elasticBackendName := c.getElasticsearchBackendConnector().Name
509-
var relationalDBBackendName string
510-
if relationalDBBackend, _ := c.getRelationalDBBackendConnector(); relationalDBBackend != nil {
511-
relationalDBBackendName = relationalDBBackend.Name
512-
}
513-
514523
conf.IndexConfig = make(map[string]IndexConfiguration)
515524
for indexName, indexConfig := range queryProcessor.Config.IndexConfig {
516525
processedConfig := indexConfig
517526
processedConfig.Name = indexName
518527

519-
if slices.Contains(indexConfig.Target, elasticBackendName) {
520-
processedConfig.QueryTarget = append(processedConfig.QueryTarget, ElasticsearchTarget)
521-
}
522-
if slices.Contains(indexConfig.Target, relationalDBBackendName) {
523-
processedConfig.QueryTarget = append(processedConfig.QueryTarget, ClickhouseTarget)
528+
for _, target := range indexConfig.Target {
529+
if targetType, found := c.getTargetType(target); found {
530+
processedConfig.QueryTarget = append(processedConfig.QueryTarget, targetType)
531+
} else {
532+
errAcc = multierror.Append(errAcc, fmt.Errorf("invalid target %s in configuration of index %s", target, indexName))
533+
}
524534
}
525535

526-
if len(processedConfig.QueryTarget) == 2 && !(indexConfig.Target[0] == relationalDBBackendName && indexConfig.Target[1] == elasticBackendName) {
536+
if len(processedConfig.QueryTarget) == 2 && !(processedConfig.QueryTarget[0] == ClickhouseTarget && processedConfig.QueryTarget[1] == ElasticsearchTarget) {
527537
errAcc = multierror.Append(errAcc, fmt.Errorf("index %s has invalid dual query target configuration - when you specify two targets, ClickHouse has to be the primary one and Elastic has to be the secondary one", indexName))
528538
continue
529539
}
@@ -566,27 +576,22 @@ func (c *QuesmaNewConfiguration) TranslateToLegacyConfig() QuesmaConfiguration {
566576
goto END
567577
}
568578

569-
elasticBackendName := c.getElasticsearchBackendConnector().Name
570-
var relationalDBBackendName string
571-
if relationalDBBackend, _ := c.getRelationalDBBackendConnector(); relationalDBBackend != nil {
572-
relationalDBBackendName = relationalDBBackend.Name
573-
}
574-
575579
conf.IndexConfig = make(map[string]IndexConfiguration)
576580
for indexName, indexConfig := range queryProcessor.Config.IndexConfig {
577581
processedConfig := indexConfig
578582
processedConfig.Name = indexName
579583

580584
processedConfig.IngestTarget = DefaultIngestTarget
581585

582-
if slices.Contains(indexConfig.Target, elasticBackendName) {
583-
processedConfig.QueryTarget = append(processedConfig.QueryTarget, ElasticsearchTarget)
584-
}
585-
if slices.Contains(indexConfig.Target, relationalDBBackendName) {
586-
processedConfig.QueryTarget = append(processedConfig.QueryTarget, ClickhouseTarget)
586+
for _, target := range indexConfig.Target {
587+
if targetType, found := c.getTargetType(target); found {
588+
processedConfig.QueryTarget = append(processedConfig.QueryTarget, targetType)
589+
} else {
590+
errAcc = multierror.Append(errAcc, fmt.Errorf("invalid target %s in configuration of index %s", target, indexName))
591+
}
587592
}
588593

589-
if len(processedConfig.QueryTarget) == 2 && !(indexConfig.Target[0] == relationalDBBackendName && indexConfig.Target[1] == elasticBackendName) {
594+
if len(processedConfig.QueryTarget) == 2 && !(processedConfig.QueryTarget[0] == ClickhouseTarget && processedConfig.QueryTarget[1] == ElasticsearchTarget) {
590595
errAcc = multierror.Append(errAcc, fmt.Errorf("index %s has invalid dual query target configuration - when you specify two targets, ClickHouse has to be the primary one and Elastic has to be the secondary one", indexName))
591596
continue
592597
}
@@ -616,11 +621,12 @@ func (c *QuesmaNewConfiguration) TranslateToLegacyConfig() QuesmaConfiguration {
616621
}
617622

618623
processedConfig.IngestTarget = make([]string, 0) // reset previously set DefaultIngestTarget
619-
if slices.Contains(indexConfig.Target, elasticBackendName) {
620-
processedConfig.IngestTarget = append(processedConfig.IngestTarget, ElasticsearchTarget)
621-
}
622-
if slices.Contains(indexConfig.Target, relationalDBBackendName) {
623-
processedConfig.IngestTarget = append(processedConfig.IngestTarget, ClickhouseTarget)
624+
for _, target := range indexConfig.Target {
625+
if targetType, found := c.getTargetType(target); found {
626+
processedConfig.IngestTarget = append(processedConfig.IngestTarget, targetType)
627+
} else {
628+
errAcc = multierror.Append(errAcc, fmt.Errorf("invalid target %s in configuration of index %s", target, indexName))
629+
}
624630
}
625631

626632
conf.IndexConfig[indexName] = processedConfig

quesma/table_resolver/rules.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,7 @@ func (r *tableRegistryImpl) singleIndex(indexConfig map[string]config.IndexConfi
126126

127127
case QueryPipeline:
128128

129-
if (targets[0] == config.ClickhouseTarget && targets[1] == config.ElasticsearchTarget) ||
130-
(targets[0] == config.ElasticsearchTarget && targets[1] == config.ClickhouseTarget) {
129+
if targets[0] == config.ClickhouseTarget && targets[1] == config.ElasticsearchTarget {
131130

132131
return &Decision{
133132
Reason: "Enabled in the config. A/B testing.",

0 commit comments

Comments
 (0)