Skip to content

Fixes 30008: Improve server startup and write-path latency#30009

Open
harshach wants to merge 15 commits into
mainfrom
harshach/perf-analysis-startup-latency
Open

Fixes 30008: Improve server startup and write-path latency#30009
harshach wants to merge 15 commits into
mainfrom
harshach/perf-analysis-startup-latency

Conversation

@harshach

@harshach harshach commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Describe your changes:

Fixes #30008

I improved server startup, request/write latency, and lineage query performance because warm boots repeated bundled-data and search reconciliation, writes repeated JSON serialization, and the pipeline-summary service type was interpolated into SQL.

Type of change:

  • Improvement

High-level design:

  • Startup observability: ordered step timings, slow-resource attribution, standard request-latency buckets, and opt-in percentile histograms
  • Warm-start path: SHA-256 gates for bundled seed data and search templates, an indexed hard-row presence check for every required bundled seed entity, failure-safe retries, bounded parallel index initialization, and database-backed type-registry hydration
  • Classpath/auth path: one shared ClassGraph scan, one cached classpath resource index, and bounded RBAC SpEL memoization
  • Write path: direct Jakarta JSON-P conversion, replayable TokenBuffer retry snapshots, storage-JSON reuse for cache write-through, and lifecycle snapshot gating
  • Database path: bound pipeline-summary filters plus MySQL generated-column and PostgreSQL expression indexes for pipeline lineage
  • Rollout: startup gates default on with force/disable controls; fingerprint persistence uses the existing settings table; lineage DDL is supplied for both databases
  • Compatibility: AI control FQNs are now framework-qualified; this entity is only on unreleased 2.0.0-SNAPSHOT, so no production migration is required, but development databases that already seeded flat control FQNs should be reset
  • Alternatives: duplicate MySQL pipeline-name DDL was rejected because migration 1.2.0 already creates it; Flowable/Quartz deferral remains evidence-gated behind the new timing data

Tests:

Use cases covered

  • First, unchanged, changed, failed, and forced seed/template fingerprint decisions
  • Matching seed fingerprints with hard-missing required rows rerun seed loaders; matching search checksums verify live template markers; probe failures fail open and intentionally deletable seeds remain optional
  • Parallel index creation and template acknowledgement/failure handling
  • PATCH conversion equivalence, replayable retry state, cache JSON reuse, and lifecycle snapshot suppression
  • Pipeline-summary filtering/pagination and quote-containing service-type input
  • Pipeline-reference lineage relation precedence and source-lineage deletion
  • Forced-deadlock update replay without double version bumps or consolidation corruption

Unit tests

  • I added unit tests for the new/changed logic.
  • Files added/updated: CommonUtilTest, StartupTimerTest, SeedDataGateTest, FrameworkSeedLoaderTest, ClasspathScanIndexTest, CollectionRegistryTest, RBACConditionEvaluatorCacheTest, IndexTemplateManagerTest, EntityRepositoryStorageJsonReuseTest, EntityLifecycleEventDispatcherTest, RequestLatencyContextTest, MicrometerBundleTest, SettingsRowMapperTest, and JsonUtilsTest
  • Final review-focused result: SeedDataGateTest and FrameworkSeedLoaderTest passed 9/9 combined; IndexTemplateManagerTest passed 10/10
  • Coverage %: not measured

Backend integration tests

  • I added integration tests in openmetadata-integration-tests/ for new/changed backend behavior.
  • Files added/updated: PipelineResourceIT.java, LineageResourceIT.java, SeedDataPresenceIT.java, AIFrameworkControlResourceIT.java, and IndexTemplateIT.java
  • MySQL 8.3 + Elasticsearch 9.3: 3 pipeline/lineage tests passed
  • PostgreSQL 15 + OpenSearch 3.4: 3 pipeline/lineage tests passed
  • MySQL 8.3 + Elasticsearch 9.3: 2 forced-deadlock replay tests passed
  • The seed-presence, AI control collision, and search-template integration sources compile; local container execution was blocked before test discovery because exhausted Docker VM storage prevented Testcontainers from creating a container

Ingestion integration tests

  • Not applicable (no ingestion changes).

Playwright (UI) tests

  • Not applicable (no UI changes).

Manual testing performed

  1. Ran clean specification generation/install and compiled service plus integration-test sources
  2. Ran MySQL and PostgreSQL migration smoke checks
  3. Ran mvn spotless:apply, mvn spotless:check, schema validation, and git diff --check

UI screen recording / screenshots:

Not applicable.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes <issue-number>: <short explanation>
  • My PR is linked to a GitHub issue via Fixes #<issue-number> above.
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.
  • For UI changes: not applicable; this PR has no UI changes.
  • I have added tests (unit / integration / Playwright as applicable) and listed them above.
  • I have added tests around the new logic.

Greptile Summary

This PR improves startup checks, search setup, and write-path performance. The main changes are:

  • Startup fingerprints for bundled seed data and search templates.
  • Required seeded-row checks before skipping warm-start reconciliation.
  • Live search-template fingerprint checks before skipping template updates.
  • Bounded parallel search-index initialization.
  • Pipeline summary query binding and lineage indexes.
  • JSON conversion and lifecycle dispatch optimizations.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.
  • The seed warm-start path now checks required database rows before skipping reconciliation.
  • The search-template path now checks live cluster markers before skipping template writes.

Important Files Changed

Filename Overview
openmetadata-service/src/main/java/org/openmetadata/service/seeding/SeedDataGate.java Adds startup seed fingerprints, required-row drift checks, failure tracking, and clean-state stamping.
openmetadata-service/src/main/java/org/openmetadata/service/seeding/RequiredSeedRows.java Defines the seed identity manifest used by the warm-start presence check.
openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CollectionDAO.java Adds the required-seed row count query and binds pipeline summary service-type filters.
openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java Adds parallel index initialization and live template fingerprint verification before skipping template writes.
openmetadata-service/src/main/java/org/openmetadata/service/search/GenericClient.java Defines template fingerprint metadata and client APIs for reading live template markers.
openmetadata-service/src/main/java/org/openmetadata/service/search/elasticsearch/ElasticSearchGenericManager.java Persists and reads Elasticsearch template fingerprints in composable template metadata.
openmetadata-service/src/main/java/org/openmetadata/service/search/opensearch/OpenSearchGenericManager.java Persists and reads OpenSearch template fingerprints using the OpenSearch-adjusted mapping content.

Comments Outside Diff (1)

  1. openmetadata-service/src/main/java/org/openmetadata/service/seeding/SeedDataGate.java, line 3187-3191 (link)

    P1 Seed rows still skip This drift check only verifies types, non-deletable policies, and non-deletable roles. The startup fingerprint covers all bundled json/data/* seed files, and many seed loaders now return before their per-row insert checks when shouldSeed() is false. If STARTUP_CHECKSUMS survives a restore while seeded rows such as bots, docstore rows, task form schemas, test definitions, tags, workflow definitions, or notification templates are missing, this check can still mark the database clean and skip the loaders. Those defaults remain absent until an operator forces seeding.

Reviews (14): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Context used (3)

  • Context used - CLAUDE.md (source)
  • Context used - openmetadata-ui-core-components/CLAUDE.md (source)
  • Context used - AGENTS.md (source)

@github-actions github-actions Bot added backend safe to test Add this label to run secure Github workflows on PRs labels Jul 14, 2026
Comment thread common/src/main/java/org/openmetadata/common/utils/CommonUtil.java
@harshach
harshach marked this pull request as ready for review July 14, 2026 04:22
Copilot AI review requested due to automatic review settings July 14, 2026 04:22
@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

✅ PR checks passed

The linked issue has a description and all required Shipping project fields set. Thanks!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown
Contributor

✅ TypeScript Types Auto-Updated

The generated TypeScript types have been automatically updated based on JSON schema changes in this PR.

Copilot AI review requested due to automatic review settings July 14, 2026 04:26
@github-actions
github-actions Bot requested a review from a team as a code owner July 14, 2026 04:26
@harshach
harshach removed the request for review from Copilot July 14, 2026 04:26
Copilot AI review requested due to automatic review settings July 14, 2026 04:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 65%
65.21% (75823/116264) 48.96% (45167/92240) 49.84% (13677/27441)

Copilot AI review requested due to automatic review settings July 19, 2026 17:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gitar-bot

gitar-bot Bot commented Jul 19, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 7 resolved / 7 findings

Improves server startup and write-path performance through fingerprint-gated seeding, parallelized index initialization, and shared classpath scanning. Resolved all identified seed drift and framework qualification issues during the review session.

✅ 7 resolved
Bug: CommonUtil.getResources now returns an immutable list

📄 common/src/main/java/org/openmetadata/common/utils/CommonUtil.java:63-77
getResources() now returns stream()...toList() over an immutable index (buildClasspathResourceIndex uses List.copyOf), whereas it previously returned a mutable ArrayList. Any caller that mutates the returned list (add/remove/sort) will now throw UnsupportedOperationException at runtime. The new CommonUtilTest even asserts this immutability. Please confirm no downstream caller of getResources()/getJsonDataResources() mutates the result; if any does, wrap it in a new ArrayList or fix the caller.

Performance: Search-template gate never stamps fingerprint if any mapping is missing

📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java:582 📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java:595-599 📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java:607-621
In createOrUpdateIndexTemplates, failed is initialized to entityIndexMap.size() - templates.size(). buildIndexTemplateDefinitions() silently drops any entity whose mapping content is null or fails to read, so templates.size() can be permanently smaller than entityIndexMap.size(). That makes failed > 0 on every boot, which triggers recordSearchTemplateFailure() (resetting the stored fingerprint to null). As a result the search-template gate never records a clean fingerprint and templates are rebuilt on every startup, defeating the warm-start optimization this PR adds. Consider only counting genuine per-template failures (increment inside the catch block) rather than pre-charging failed with the count of skipped/no-mapping entities.

Quality: ClasspathScanIndex keeps ScanResult open for JVM lifetime

📄 openmetadata-service/src/main/java/org/openmetadata/service/util/ClasspathScanIndex.java:32-39 📄 openmetadata-service/src/main/java/org/openmetadata/service/util/ClasspathScanIndex.java:45-57
The new ClasspathScanIndex singleton opens a ClassGraph ScanResult in its constructor and never closes it, whereas the previous CollectionRegistry/Entity code wrapped the scan in try-with-resources. The loaded classes are cached in the two maps, so the ScanResult itself no longer needs to stay open after warmup; retaining it holds ClassGraph's class-graph metadata (and any file handles) for the life of the process. Consider closing the ScanResult after populating the caches, or eagerly materializing the needed lookups and closing the scan.

Edge Case: Seed-data gate skips reseeding on DB drift when files are unchanged

📄 openmetadata-service/src/main/java/org/openmetadata/service/seeding/SeedDataGate.java:96-101 📄 openmetadata-service/src/main/java/org/openmetadata/service/seeding/SeedDataGate.java:173-187 📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java:1408-1413
SeedDataGate.shouldSeed() decides whether to seed based solely on a fingerprint of the classpath seed resources plus server version, compared to the fingerprint persisted in the settings table. If seed rows (roles, policies, bootstrap types, etc.) are removed or corrupted out-of-band while the seed files remain unchanged, a restart will skip reseeding and leave the system missing required seed data. This is mitigated by STARTUP_FORCE_SEED_DATA / seedDataGateEnabled=false, but the failure mode is silent. Consider documenting this operational caveat prominently, or gating on a lightweight presence check in addition to the file fingerprint.

Edge Case: Warm-start seed gate reseeds every boot when email config is unset

📄 openmetadata-service/src/main/java/org/openmetadata/service/seeding/SeedDataGate.java:313-324 📄 openmetadata-service/src/main/java/org/openmetadata/service/seeding/RequiredSeedRows.java:55-67
When no EMAIL_CONFIGURATION settings row exists, SeedDataGate.getEmailTemplateProvider() returns null (SeedDataGate.java:316-317), and RequiredSeedRows.selectEmailDocuments(null) then requires BOTH openmetadata and collate email documents to be present (RequiredSeedRows.java:58-60). However the actual seeder DocumentRepository.getEntitiesFromSeedData() loads only ONE provider's templates — defaulting to openmetadata (DocumentRepository.java:64-75) via SettingsCache which returns the OPENMETADATA default rather than null. As a result the collate email documents are never seeded, hasRequiredSeedRows always returns false, and the drift check reseeds on every warm boot — defeating the startup optimization this PR introduces. Make getEmailTemplateProvider default to OPENMETADATA when the config row is absent (mirroring the seeder / DefaultOperationalConfigProvider), instead of returning null.

...and 2 more resolved from earlier reviews

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

…s-startup-latency

# Conflicts:
#	bootstrap/sql/migrations/native/2.0.0/mysql/schemaChanges.sql
#	bootstrap/sql/migrations/native/2.0.0/postgres/schemaChanges.sql
#	openmetadata-service/src/main/java/org/openmetadata/service/events/lifecycle/EntityLifecycleEventDispatcher.java
#	openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/CollectionDAO.java
#	openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java
#	openmetadata-spec/src/main/resources/json/schema/settings/settings.json
#	openmetadata-ui/src/main/resources/ui/src/generated/settings/settings.ts

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions

Copy link
Copy Markdown
Contributor

✅ TypeScript Types Auto-Updated

The generated TypeScript types have been automatically updated based on JSON schema changes in this PR.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Comment on lines +84 to +87
private static final Set<SeedTable> REQUIRED_SEED_TABLES =
EnumSet.complementOf(
EnumSet.of(
SeedTable.DATA_INSIGHT_CUSTOM_CHART, SeedTable.GLOSSARY, SeedTable.GLOSSARY_TERM));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Glossary Seeds Still Skip The required-row check excludes glossary and glossary-term seed rows even though those bundled resources are included in the startup fingerprint and the glossary loader is gated by shouldSeed(). When the stored checksum still matches but a restore or direct cleanup removes bundled glossary rows, this set can still mark the database clean, skip the loader, and leave the default glossary data missing across warm boots.

Comment on lines +634 to +648
private int createMissingIndexesInParallel(int parallelism) {
List<Callable<Boolean>> tasks =
entityIndexMap.entrySet().stream()
.<Callable<Boolean>>map(entry -> () -> createMissingIndex(entry))
.toList();
try (ExecutorService executor =
Executors.newFixedThreadPool(
parallelism, Thread.ofPlatform().name("search-init-", 0).factory())) {
int created = 0;
for (Future<Boolean> result : executor.invokeAll(tasks)) {
try {
if (result.get()) {
created++;
}
} catch (ExecutionException exception) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Edge Case: Parallel search-index init assumes thread-safe client calls

createMissingIndexesInParallel runs createMissingIndex (indexExists/createIndex/reconcileAliases) across up to STARTUP_SEARCH_INIT_PARALLELISM (default 8) threads simultaneously. This is correct only if the underlying ElasticSearch/OpenSearch client and the shared entityIndexMap accesses are thread-safe; any shared mutable state in reconcileAliases/createIndex could race during startup. Since results are only aggregated via Future.get(), a silent inconsistency (rather than a failure) would be hard to detect. Confirm the search client and alias reconciliation are safe under concurrency, or serialize the alias-reconcile step.

Was this helpful? React with 👍 / 👎

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

…s-startup-latency

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gitar-bot

gitar-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown
Code Review 👍 Approved with suggestions 9 resolved / 10 findings

Improves server startup and write-path performance via seed fingerprinting and optimized classpath scanning. Ensure that the parallel search-index initialization logic correctly accounts for potential thread-safety limitations in client calls.

💡 Edge Case: Parallel search-index init assumes thread-safe client calls

📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java:634-648

createMissingIndexesInParallel runs createMissingIndex (indexExists/createIndex/reconcileAliases) across up to STARTUP_SEARCH_INIT_PARALLELISM (default 8) threads simultaneously. This is correct only if the underlying ElasticSearch/OpenSearch client and the shared entityIndexMap accesses are thread-safe; any shared mutable state in reconcileAliases/createIndex could race during startup. Since results are only aggregated via Future.get(), a silent inconsistency (rather than a failure) would be hard to detect. Confirm the search client and alias reconciliation are safe under concurrency, or serialize the alias-reconcile step.

✅ 9 resolved
Bug: CommonUtil.getResources now returns an immutable list

📄 common/src/main/java/org/openmetadata/common/utils/CommonUtil.java:63-77
getResources() now returns stream()...toList() over an immutable index (buildClasspathResourceIndex uses List.copyOf), whereas it previously returned a mutable ArrayList. Any caller that mutates the returned list (add/remove/sort) will now throw UnsupportedOperationException at runtime. The new CommonUtilTest even asserts this immutability. Please confirm no downstream caller of getResources()/getJsonDataResources() mutates the result; if any does, wrap it in a new ArrayList or fix the caller.

Performance: Search-template gate never stamps fingerprint if any mapping is missing

📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java:582 📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java:595-599 📄 openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java:607-621
In createOrUpdateIndexTemplates, failed is initialized to entityIndexMap.size() - templates.size(). buildIndexTemplateDefinitions() silently drops any entity whose mapping content is null or fails to read, so templates.size() can be permanently smaller than entityIndexMap.size(). That makes failed > 0 on every boot, which triggers recordSearchTemplateFailure() (resetting the stored fingerprint to null). As a result the search-template gate never records a clean fingerprint and templates are rebuilt on every startup, defeating the warm-start optimization this PR adds. Consider only counting genuine per-template failures (increment inside the catch block) rather than pre-charging failed with the count of skipped/no-mapping entities.

Quality: ClasspathScanIndex keeps ScanResult open for JVM lifetime

📄 openmetadata-service/src/main/java/org/openmetadata/service/util/ClasspathScanIndex.java:32-39 📄 openmetadata-service/src/main/java/org/openmetadata/service/util/ClasspathScanIndex.java:45-57
The new ClasspathScanIndex singleton opens a ClassGraph ScanResult in its constructor and never closes it, whereas the previous CollectionRegistry/Entity code wrapped the scan in try-with-resources. The loaded classes are cached in the two maps, so the ScanResult itself no longer needs to stay open after warmup; retaining it holds ClassGraph's class-graph metadata (and any file handles) for the life of the process. Consider closing the ScanResult after populating the caches, or eagerly materializing the needed lookups and closing the scan.

Edge Case: Seed-data gate skips reseeding on DB drift when files are unchanged

📄 openmetadata-service/src/main/java/org/openmetadata/service/seeding/SeedDataGate.java:96-101 📄 openmetadata-service/src/main/java/org/openmetadata/service/seeding/SeedDataGate.java:173-187 📄 openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/EntityRepository.java:1408-1413
SeedDataGate.shouldSeed() decides whether to seed based solely on a fingerprint of the classpath seed resources plus server version, compared to the fingerprint persisted in the settings table. If seed rows (roles, policies, bootstrap types, etc.) are removed or corrupted out-of-band while the seed files remain unchanged, a restart will skip reseeding and leave the system missing required seed data. This is mitigated by STARTUP_FORCE_SEED_DATA / seedDataGateEnabled=false, but the failure mode is silent. Consider documenting this operational caveat prominently, or gating on a lightweight presence check in addition to the file fingerprint.

Edge Case: Warm-start seed gate reseeds every boot when email config is unset

📄 openmetadata-service/src/main/java/org/openmetadata/service/seeding/SeedDataGate.java:313-324 📄 openmetadata-service/src/main/java/org/openmetadata/service/seeding/RequiredSeedRows.java:55-67
When no EMAIL_CONFIGURATION settings row exists, SeedDataGate.getEmailTemplateProvider() returns null (SeedDataGate.java:316-317), and RequiredSeedRows.selectEmailDocuments(null) then requires BOTH openmetadata and collate email documents to be present (RequiredSeedRows.java:58-60). However the actual seeder DocumentRepository.getEntitiesFromSeedData() loads only ONE provider's templates — defaulting to openmetadata (DocumentRepository.java:64-75) via SettingsCache which returns the OPENMETADATA default rather than null. As a result the collate email documents are never seeded, hasRequiredSeedRows always returns false, and the drift check reseeds on every warm boot — defeating the startup optimization this PR introduces. Make getEmailTemplateProvider default to OPENMETADATA when the config row is absent (mirroring the seeder / DefaultOperationalConfigProvider), instead of returning null.

...and 4 more resolved from earlier reviews

🤖 Prompt for agents
Code Review: Improves server startup and write-path performance via seed fingerprinting and optimized classpath scanning. Ensure that the parallel search-index initialization logic correctly accounts for potential thread-safety limitations in client calls.

1. 💡 Edge Case: Parallel search-index init assumes thread-safe client calls
   Files: openmetadata-service/src/main/java/org/openmetadata/service/search/SearchRepository.java:634-648

   createMissingIndexesInParallel runs createMissingIndex (indexExists/createIndex/reconcileAliases) across up to STARTUP_SEARCH_INIT_PARALLELISM (default 8) threads simultaneously. This is correct only if the underlying ElasticSearch/OpenSearch client and the shared entityIndexMap accesses are thread-safe; any shared mutable state in reconcileAliases/createIndex could race during startup. Since results are only aggregated via Future.get(), a silent inconsistency (rather than a failure) would be hard to detect. Confirm the search client and alias reconciliation are safe under concurrency, or serialize the alias-reconcile step.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend safe to test Add this label to run secure Github workflows on PRs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Improve server startup and write-path latency

2 participants