Conversation
ChrisPdgn
marked this pull request as ready for review
September 17, 2026 09:14
Make schema indexes first-class on Mongo, PostgreSQL, MySQL, MariaDB, and SQLite. Platform models use Compatible Ascending/Descending so the same declarations create live indexes on every dialect. Admin create/get/delete/import/export persist into _DeclaredSchema without a full schema rebuild.
Repair the ModelOptionsIndexTypes union that failed tsc, stop stuffing Sequelize field objects into Conduit index types, and move the index suites into src/__tests__/indexes.
Adopt engine names by fields+unique so upgrades and custom modules do not create duplicate indexes, keep Admin extras across re-register, persist only applied create/delete subsets, and publish bound names to replicas.
Read _DeclaredSchema from primary before index persist, reuse SQL name-exists errors only when fields+unique match, and freeze registeredSchemas after bind/save so replica catch-up gets live names.
…ySQL Fail-soft Mongo GET/export on missing collections. Qualify generated index names by table and bind live names without rename. Skip MySQL JSON btree and SQL extracted-relation indexes on register; reject them from Admin. Lift Mongo array Compatible indexes to createIndexes. Register Database, Authz, and Chat schemas sequentially.
Keep Chat and Authorization registerSchemas on Promise.all, matching other Conduit modules. Sequential register stays in Database onServerStart.
Publish the Sequelize adapter into models before resolving relations and wait for the related adapter to exist instead of .synced so Promise.all Chat register cannot deadlock on that cycle.
Map ChatMessage.room to engine roomId for SQL bind/create/get while keeping index names on declared fields. Array/extracted Relations (ChatRoom.participants) and MySQL JSON btree stay skipped. Authz String *Id fields are left unchanged.
Compatible-index createIndexes binds against live Mongo indexes, so the vector lifecycle mock must expose collection.indexes() for both features to share the same adapter path after the rebase onto main. Co-authored-by: Christina Papadogianni <ChrisPdgn@users.noreply.github.com>
cursor
Bot
force-pushed
the
feat/database-dialect-indexes
branch
from
September 17, 2026 09:25
4bcc20b to
a7fe0f4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Rewrite of the approved #643 index work from current
origin/main(not a cherry-pick/rebase of the staleindexesbranch).Schema indexes are now first-class on MongoDB, PostgreSQL, MySQL, MariaDB, and SQLite. Platform models (authorization + chat) declare
CompatibleIndexTypeAscending/Descending so the same indexes exist on SQL too.What this does
CompatibleIndexType(Ascending/Descending) plus optionalunique. Maps to Mongo1/-1and SQLBTREE ASC/DESC.cnd_idx_*/cnd_uidx_*name.sync(), so upgrades do not throw Mongo 86 or create a second SQL btree._DeclaredSchemasurvive module re-register. Stale generated names for an identity now bound to a live name are dropped. Leftover live indexes are not dropped on register; usedeleteIndexes._DeclaredSchema. No full schema rebuild/sync()for Admin index create/delete._DeclaredSchemafrom primary. SQL same-name conflicts (42P07/1061) reuse only when fields+unique match; same name with different fields throws.getIndexesuses the live engine as source of truth and overlays declared types by name, then by identity.publishSchemanotifies replicas.registeredSchemasis snapshotted after bind/save so replica catch-up sends live names. Replicas useinstanceSync=trueand do not create indexes.originalSchema.collectionNameeverywhere (no hardcodedcnd_prefix).skip/limit). Same-name indexes are skipped on import; create still binds by identity so it cannot duplicate a live index on the same fields.validateModelOptionsacceptsindexesand still allowsconduit.readPreference.dropIndexis awaited.autoIndexis off.SQL scalar Relation indexes
Sequelize stores a scalar Relation such as ChatMessage
roomasroomId. Indexes now follow that mapping instead of skipping every Relation:room↔ engine columnroomIdfor SQL bind / create / get. LiveroomIdcompounds adopt the declaredroomidentity.room, notroomId), so Mongo and SQL keep the samecnd_idx_*labels.*Idfields (resourceId,subjectId, …) are not rewritten. Only actual scalar Relation fields get theIdsuffix.participantscompounds are still skipped.inheritanceTree).modelOptions.indexesbeforeextractRelations. Field-level array Relations are still skipped.roomId→roomwhenroomis a scalar Relation.getIndexes/ export return declared names.instanceSyncis unchanged (replicas do not create indexes).Related SQL register fixes on this branch
Promise.allagain.sync()first.Intentionally not changed / not ported
getDatabaseType()still returns'PostgreSQL'(no'postgres'rename).ActorIndex/ObjectIndexdocuments — only their schema index declarations changed to Compatible.case 'mysql' || 'mariadb', metadata-onlygetIndexes,createSchemaFromAdapterrebuild for indexes, unbounded export, required index names, import always treating unique as database-owned, ReverseMongoIndexTypeMap display-name round-trip.fields.*.indexfrom module source after Admin deleted that field index, indexing array/extracted Relations on the parent table, MySQL JSON Compatible btree.Fixes #643 (implementation rewrite; this PR does not close or merge #643 by itself).
Type of change
How Has This Been Tested?
Unit tests in
modules/database/src/__tests__/indexes/(bind, unique-collision vs name-exists, extras union, partial persist, overlay-by-identity, primary persist read, SQL same-name/different-fields, publish, declaredroom↔ engineroomId, Authz String*Idsafety, ChatRoomparticipantsskip, Admin canonicalize):Result: 5 suites, 92 passed.
tsc --noEmitinmodules/databaseis clean (after proto codegen).Live-engine integration tests were not run in this environment (no Mongo/SQL). Recommended follow-up smoke:
room/roomIdcompounds on PostgreSQL and MySQLparticipantsstill skipped*Idunchanged (resourcestaysresource)Test Configuration:
@conduitplatform/database,@conduitplatform/grpc-sdkChecklist:
Remaining risks
showIndexrow shapes differ by SQL dialect; unusual engine-specific indexes may normalize oddly.DESCuses Sequelize{ name, order }field objects — worth a live MySQL/MariaDB/SQLite check.roomIdwhile Admin/export now speak declaredroom. Older exports that usedroomIdare canonicalized on import whenroomis a scalar Relation.*Idwould become*IdId(Sequelizerelation + 'Id'). None of the platform models do that.