Skip to content

[OPIK-5437] [BE] fix: correct agent configuration version ordering#6071

Merged
BorisTkachenko merged 3 commits intomainfrom
boryst/OPIK-5437-agent-configuration-version-numbers-are-not-displayed-in-the-correct-order
Apr 7, 2026
Merged

[OPIK-5437] [BE] fix: correct agent configuration version ordering#6071
BorisTkachenko merged 3 commits intomainfrom
boryst/OPIK-5437-agent-configuration-version-numbers-are-not-displayed-in-the-correct-order

Conversation

@BorisTkachenko
Copy link
Copy Markdown
Contributor

Details

Agent configuration version numbers were not displayed in the correct order because blueprint history was sorted by id (UUID) instead of created_at timestamp. This change fixes the ordering and also makes the distributed lock duration for blueprint create/update operations configurable via AgentConfigConfiguration.

  • Changed ORDER BY b.id DESC to ORDER BY b.created_at DESC in blueprint history query
  • Replaced fixed lock durations with configurable blueprintLockDuration (default 5000ms) using executeWithLockCustomExpire
  • Added AgentConfigConfiguration class and wired it through Dropwizard/Guice config

Change checklist

  • User facing
  • Documentation update

Issues

  • OPIK-5437

AI-WATERMARK

AI-WATERMARK: yes

  • If yes:
    • Tools: Claude Code (Claude Opus 4.6)
    • Model(s): claude-opus-4-6
    • Scope: PR description generation
    • Human verification: yes

Testing

  • Verified blueprint history ordering now uses created_at instead of UUID-based id
  • Confirmed configurable lock duration is injected via Guice and defaults to 5000ms
  • Backend compilation: mvn compile -DskipTests

Documentation

N/A

@BorisTkachenko BorisTkachenko self-assigned this Apr 3, 2026
@BorisTkachenko BorisTkachenko requested a review from a team as a code owner April 3, 2026 08:54
@github-actions github-actions bot added java Pull requests that update Java code Backend labels Apr 3, 2026
Comment thread apps/opik-backend/src/main/java/com/comet/opik/domain/AgentConfigDAO.java Outdated
Comment thread apps/opik-backend/config.yml
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

Backend Tests - Integration Group 15

273 tests  +31   273 ✅ +31   4m 46s ⏱️ -4s
 19 suites  -  6     0 💤 ± 0 
 19 files    -  6     0 ❌ ± 0 

Results for commit f9f1b26. ± Comparison against base commit d295a1e.

This pull request removes 33 and adds 64 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ datasetsRedirectTest(String, String, int)[1]
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ datasetsRedirectTest(String, String, int)[2]
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ datasetsRedirectTest(String, String, int)[3]
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ datasetsRedirectUrlNoDataset
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ experimentsRedirectTest(String, String, int)[1]
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ experimentsRedirectTest(String, String, int)[2]
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ experimentsRedirectTest(String, String, int)[3]
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ experimentsRedirectUrlNoDataset
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ optimizationsRedirectTest(String, String, int)[1]
com.comet.opik.api.resources.v1.session.RedirectResourceTest ‑ optimizationsRedirectTest(String, String, int)[2]
…
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets__whenFetchingAllDatasets__thenReturnDatasetsSortedByCreatedDate
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets__whenFetchingAllDatasets__thenReturnDatasetsSortedByValidFields(Comparator, SortingField)[10]
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets__whenFetchingAllDatasets__thenReturnDatasetsSortedByValidFields(Comparator, SortingField)[11]
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets__whenFetchingAllDatasets__thenReturnDatasetsSortedByValidFields(Comparator, SortingField)[12]
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets__whenFetchingAllDatasets__thenReturnDatasetsSortedByValidFields(Comparator, SortingField)[13]
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets__whenFetchingAllDatasets__thenReturnDatasetsSortedByValidFields(Comparator, SortingField)[14]
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets__whenFetchingAllDatasets__thenReturnDatasetsSortedByValidFields(Comparator, SortingField)[15]
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets__whenFetchingAllDatasets__thenReturnDatasetsSortedByValidFields(Comparator, SortingField)[16]
com.comet.opik.api.resources.v1.priv.DatasetsResourceFindProjectDatasetsTest ‑ getProjectDatasets__whenFetchingAllDatasets__thenReturnDatasetsSortedByValidFields(Comparator, SortingField)[17]
…

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 3, 2026

TS SDK E2E Tests - Node 22

275 tests  ±0   273 ✅ ±0   16m 54s ⏱️ + 2m 6s
 32 suites ±0     2 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 11d5651. ± Comparison against base commit d295a1e.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 7, 2026

Backend Tests - Integration Group 16

 15 files  ± 0   15 suites  ±0   5m 19s ⏱️ -8s
227 tests + 2  225 ✅ + 3  2 💤  - 1  0 ❌ ±0 
152 runs   - 73  150 ✅  - 72  2 💤  - 1  0 ❌ ±0 

Results for commit ad55d86. ± Comparison against base commit d295a1e.

This pull request removes 21 and adds 23 tests. Note that renamed tests count towards both.
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ datasetBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ experimentBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ mixedWorkspaceExcludesDemoData
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spanBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spansCountExcludingDemoData
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ spansCountForWorkspace
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ traceBiInfoTest
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ tracesCountExcludingDemoData
com.comet.opik.api.resources.v1.internal.UsageResourceTest$Usage ‑ tracesCountForWorkspace
com.comet.opik.api.resources.v1.priv.AttachmentResourceMinIOTest ‑ deleteTraceDeletesTraceAndSpanAttachments(Consumer)[1]
…
com.comet.opik.api.resources.v1.priv.AttachmentResourceTest ‑ directS3DownloadShouldFailTest
com.comet.opik.api.resources.v1.priv.AttachmentResourceTest ‑ directS3UploadShouldFailTest
com.comet.opik.api.resources.v1.priv.AttachmentResourceTest ‑ uploadAttachmentWithMultiPartPresignUrl
com.comet.opik.domain.retention.RetentionPolicyServiceTest$CatchUpJob ‑ noApplyToPast_catchUpDoneImmediately
com.comet.opik.domain.retention.RetentionPolicyServiceTest$CatchUpJob ‑ smallWorkspace_oneShotCatchUp
com.comet.opik.domain.retention.RetentionPolicyServiceTest$DeletionVerification ‑ deletesOnlyOldRowsAcrossAllTables
com.comet.opik.domain.retention.RetentionPolicyServiceTest$DeletionVerification ‑ deletionIsScopedToTargetWorkspaces
com.comet.opik.domain.retention.RetentionPolicyServiceTest$RetentionCycleExecution ‑ deletesExpiredDataAndKeepsRecentData
com.comet.opik.domain.retention.RetentionPolicyServiceTest$RetentionCycleExecution ‑ noRulesInRange_noDeletes
com.comet.opik.domain.retention.RetentionPolicyServiceTest$RetentionCycleExecution ‑ unlimitedRetentionRulesAreIgnored
…

♻️ This comment has been updated with latest results.

Copy link
Copy Markdown
Contributor

@LifeXplorer LifeXplorer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sorting change is functionally a no-op. This project enforces UUIDv7 exclusively, and UUIDv7 is designed so that lexicographic UUID ordering equals chronological ordering — the timestamp occupies the top 48 bits.
Since blueprint IDs are generated via idGenerator.generateId() right before insert, ORDER BY id DESC and ORDER BY created_at DESC produce identical results.
If there's a real ordering bug, the root cause is likely elsewhere. This change isn't harmful, but it may mask the actual issue — and could be slightly worse for performance if created_at isn't indexed while id (PK) is.

Copy link
Copy Markdown
Member

@andrescrz andrescrz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please review open comments before moving forward.

Comment thread apps/opik-backend/config.yml
@github-actions github-actions bot added the tests Including test files, or tests related like configuration. label Apr 7, 2026
@BorisTkachenko
Copy link
Copy Markdown
Contributor Author

@andrescrz @LifeXplorer
You are right, in normal case this should be the same as ordering by id. But this is assuming that this id is generated on the BE side. Unfortunately in our case it's generated on SDK side. And we have edge cases when SDK sends 5 blueprints within a second to BE with already generated on SDK side ids and those are not logged on the BE side with the same ordering. Since we generate also names on the BE side as V1, V2, .... but later we order by id, we ended up in a situation where name versions do not go in proper order. This won't fix root cause but at least will guarantee that ordering matches how it's saved on the BE side, as this will be used to get configuration slice.

As we discussed this is not generally a valid use case, as blueprints/configurations are not supposed to be used like this and SDK should be mindful about ordering and generally waits for blueprint creation completion before creating next one.

This was discovered during tests when script used more low level SDK functionality. It shouldn't be used like this by actual users. When we tried to reproduce with normal scenario it never happened.

Regarding performance it should be ok, even we don't have index for created_at. We do ordering only after we filter by workpsace, project and type (filter out masks). Expectation that it will be around 30-40 blueprints to order, max around 100. So it should be ok.

@BorisTkachenko BorisTkachenko merged commit 6956f1b into main Apr 7, 2026
76 checks passed
@BorisTkachenko BorisTkachenko deleted the boryst/OPIK-5437-agent-configuration-version-numbers-are-not-displayed-in-the-correct-order branch April 7, 2026 10:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backend java Pull requests that update Java code tests Including test files, or tests related like configuration.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants