Repository navigation
feat(api): run the knowledge base and file copies from the migration endpoints - #15611
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughMigration runs now support knowledge-base and file copies alongside database copies. The changes add dry-run handling, step-specific destination configuration, copy-step gating, and optional verification of knowledge bases already routed to the target. ChangesMigration copy workflow
Priority: ➖ Normal Estimated code review effort: 3 (Moderate) | ~25 minutes Change: Feature Sequence Diagram(s)sequenceDiagram
participant MigrationAPI
participant copy_environment
participant copy_command
participant CopyProcess
participant Destination
MigrationAPI->>copy_environment: Build environment for selected step
MigrationAPI->>copy_command: Build command with destinations and dry-run setting
MigrationAPI->>CopyProcess: Start copy process
CopyProcess->>Destination: Copy knowledge-base or file data
CopyProcess-->>MigrationAPI: Return copy report
MigrationAPI->>MigrationAPI: Update run and step status
Merge Risk: 🟡 Moderate · up to File migration can fail before copying begins when the server uses temporary AWS credentials. Clear the inherited session token before merging. 🚥 Pre-merge checks | ✅ 8 | ❌ 1
✨ Finishing Touches 💡 2
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
✅ Test Coverage AdvisorNo source changes detected without accompanying tests. Thanks for keeping coverage up! 🎉
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## feat/migration-runs-api #15611 +/- ##
===========================================================
- Coverage 69.88% 68.97% -0.92%
===========================================================
Files 2777 2775 -2
Lines 299516 299488 -28
Branches 40374 40392 +18
===========================================================
- Hits 209325 206572 -2753
- Misses 87697 90422 +2725
Partials 2494 2494
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
erichare
left a comment
There was a problem hiding this comment.
Reviewed 1d90561 against the preceding stack PR. The per-step environments isolate the destination credentials, dry runs remain incomplete, and rerunning the database invalidates later copies. No blocking findings introduced by this delta. Focused migration checks across the stack passed (151 tests, 12 skipped and 6 deselected). The live PostgreSQL/S3 cases were not rerun locally.
CI remains an independent gate: Python 3.14 Group 1 failed the unchanged native first-start storage test with chroma/needs_attention instead of sqlite/ready. The affected test and conversion paths are unchanged here. Parallel process-check interference is plausible but unconfirmed. Please resolve that failure before merging.
|
Thanks, @ogabrielluiz, for keeping copies pointed at the destination database and covering dry runs and rerun invalidation. Approved for this stack delta. The outstanding Python 3.14 native-storage CI failure still needs attention, and the separate copy-admission finding is tracked on #15610. |
1d90561 to
9543aef
Compare
9543aef to
d4dc4f5
Compare
d4dc4f5 to
18e367d
Compare
e9976f8 to
ea98973
Compare
|
Added in ea98973: a |
ea98973 to
fdd3001
Compare
fdd3001 to
4c28807
Compare
4c28807 to
cd18db6
Compare
…endpoints Add the other two copies to the endpoints that run a copy step: the knowledge bases into pgvector tables in the destination database, and the stored files into the destination bucket. Both take a test run, which passes --dry-run and never completes the step. Both commands work on the database the new instance will run on, so this instance's own rows stay as they are. An instance already on PostgreSQL keeps its database, and the copies work on it. The file copy signs in with the keys the admin gave. It gets none of the server's AWS_ variables, and the server's AWS config and credentials files are replaced with an empty one, so a profile, a session token or an endpoint of the server's own cannot redirect it. A report's failed items are kept in the record, the first hundred of them, and a step with one is blocked with that item's code. Copying the database again writes every row of the destination again, including the ones the other two copies changed there. So a knowledge base or file copy counts only when it started after the database copy on record. The destination's address is read with the driver its test and the database copy read it with. Taken as it was typed, an address spelled for another driver passed that test and then failed the two later copies.
…y in The checks a copy passes before it starts now come from the commits below: every step before it is done or skipped, and this worker's secrets are for the destination that is saved. Cover them for the two copies added here. A file copy is refused when the worker's keys are for another bucket than the saved one, and a knowledge base copy that was made is refused while the database copy before it is no longer done. The test that sets the bucket's keys by hand now says which bucket they are for.
An instance that already runs on PostgreSQL keeps its database, so the copy of the knowledge bases writes the vectors into it and changes the rows of the database the instance is still serving from. From then on the instance reads each knowledge base from pgvector, which it finds only through PGVECTOR_CONNECTION_STRING in its own environment. Without that variable every knowledge base stopped opening once the copy had run, and turning changes back on did not bring them back. On PostgreSQL the copy is now let in only when the server's environment names that store. Otherwise the step reads blocked with pgvector_env_missing, and starting it answers 409 with the same code.
…t reads On an instance that already runs on PostgreSQL the copy was sent to the instance's own database, and it was let in whenever the server's environment named any pgvector store. A server whose PGVECTOR_CONNECTION_STRING named another database would then read from a store the copy never wrote to. On PostgreSQL the copy is now given the server's own value of that variable, unchanged, so it writes where this server reads its knowledge bases from. The variable is asked for at every start, whatever the step reads: a copy that was made says nothing of how the server was started since.
…ther store A copy from SQLite gives relocate-kb the destination as its pgvector store. A knowledge base that was already in pgvector then names the destination, which holds none of its chunks. The command skipped it as already on the target, and the step read done. relocate-kb gets --verify-skipped. With it, a knowledge base that would be skipped has its chunks counted in its store first, unless its row records none. It fails with kb_target_short when the store holds fewer chunks than the row records, and with kb_target_unreachable when the store cannot be read. The page passes the option for a copy from SQLite. Without the option the command does what it did. Such a knowledge base is still not copied: the copy is given no way to read the server's own pgvector store. The step now ends blocked on it and says why. An instance with no knowledge base on its own disk has no such step, so one whose knowledge bases are all in pgvector still moves without them.
…told not to relocate-kb skipped a knowledge base whose row already names the target without a look at the store, and counted its chunks only with --verify-skipped. Run by hand, a knowledge base kept in another store was passed over with exit code 0. The count is now the default, and --no-verify-skipped turns it off. The migration page gives the option either way, so its copies behave as before: a copy from SQLite counts, and a copy on a PostgreSQL instance does not.
relocate-kb fails a knowledge base whose row already names the target when the store holds fewer chunks than the row records. Its reason names one cause, chunks kept in another store. A row that records too many chunks over the right store fails the same way, and the option that gets past it was only in --help. The text output now adds a hint line under such a knowledge base. It says that the option skips every knowledge base already on the target without a count. The reason and the flag stay as they are: both go to the migration page as well, and nobody there runs the command.
Stacked on the database copy PR.
relocate-kb --json(#15527) andrelocate-files --json(#15525), which it needs, have merged.This adds the other two copies to the routes that run a copy step: "Copy knowledge bases" and "Copy files". Both can be tried first with a test run. The decisions an admin can make about a copy come in the next PR.
What each step runs.
POST /api/v1/migration/steps/{id}/runsnow also takes:copy_knowledge_bases, which runslangflow relocate-kb --to postgres --jsonwith--verify-skippedor--no-verify-skipped(see below). The vectors go into the destination database as pgvector tables.copy_files, which runslangflow relocate-files --json --bucket <bucket> --prefix <prefix>, with the bucket and the prefix the record holds.{"dry_run": true}adds--dry-run. A test run says what a copy would do and never completes the step. The database copy still has none.Where they write. Both commands work on the database the new instance will run on, which the database copy filled:
LANGFLOW_DATABASE_URLis the destination database, andPGVECTOR_CONNECTION_STRINGis the same one. So this instance's own rows stay as they are, and it goes on serving its knowledge bases and files from its own disk.An instance already on PostgreSQL. It keeps its database, and the two copies work on it. The knowledge bases go to the store the server's own
PGVECTOR_CONNECTION_STRINGnames: the command is given that value unchanged, so it writes where this instance already reads pgvector knowledge bases from, whichever database that is. The copy changes theknowledge_baserows of the database the instance is still serving from, and from then on the instance reads each knowledge base from that store. So before this step the admin starts the server withPGVECTOR_CONNECTION_STRINGset, to its own database unless the vectors are to live somewhere else. Without the variable the step readsblockedwithpgvector_env_missing, and starting the copy answers 409 with the same code, whatever the step reads. A rehearsal on a real PostgreSQL instance showed what this prevents: a knowledge base that answered 200 before the copy answered 500 after it, turning changes back on did not bring it back, and a restart with the variable set did.The destination's address is read with the driver its test and the database copy read it with. Taken as it was typed, an address spelled
postgresql+asyncpg://passed the test of the destination and the database copy, and then failed both later copies with a misleadingschema_mismatch.A knowledge base the copy does not read. A copy from SQLite gives
relocate-kbthe destination as its pgvector store. A knowledge base that this server already keeps in its own pgvector store has a row that says pgvector, so in the copy it names the destination, which holds none of its chunks. The command skipped it as already on the target, and the step read done.relocate-kbnow counts first: a knowledge base that would be skipped has its chunks counted in its store, unless its row records none. Fewer chunks than the row records fails it withkb_target_short, and a store that cannot be read fails it withkb_target_unreachable, so the step ends blocked.--no-verify-skippedturns the count off, and the copy always says which it wants. From SQLite it passes--verify-skipped. On an instance on PostgreSQL it passes--no-verify-skipped: there the copy reads the server's own store, and the check step has counted every such row in it.Such a knowledge base is still not copied, because the copy is given no way to read the server's own store. In this PR the step stays blocked on it, and the decision that gets past it comes with the next PR. An instance with no knowledge base on its own disk has no such step, so one whose knowledge bases are all in pgvector still moves without them. Run by hand, the command counts as well, so it lists such a knowledge base as failed and ends with exit code 1. The page is behind a flag in this release, so the command line is how an instance gets moved, and with the count off by default it skipped that knowledge base with exit code 0. A knowledge base that is in place and whose row records too many chunks fails the same way, and
--no-verify-skippedis the way past it. Under a short count the command prints a hint line that names the option. Only the text output has the hint: the page gets the code and the reason, and nobody there types the command.The file copy and AWS. It signs in with the keys the admin gave:
AWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEY, plusAWS_ENDPOINT_URLandAWS_CA_BUNDLEwhen they were given. It gets none of the server's ownAWS_variables, andAWS_CONFIG_FILEandAWS_SHARED_CREDENTIALS_FILEpoint at an empty file. So a profile, a session token or an endpoint the server has for its own work cannot redirect the copy. No key is on the command line.The record. A report's failed items are kept under
report.attention, the first hundred of them.report.countsstill says how many failed. Every item stays in the run's events. A step whose report has a failed item is blocked with that item's code, for examplekb_metric_changeorfile_conflict.Order. Each copy is locked until the one before it is done or skipped. Copying the database again writes every row of the destination again, and with them what the other two copies changed there: where each knowledge base is kept, and how chat history names its attachments. So a knowledge base or file copy counts only when it started after the database copy on record. When the database is copied again, the other two read
currentagain.How to try it
Same
$BASE,$M,$H,$Jandfollowas in the database copy PR, on a SQLite instance with a local knowledge base and an uploaded file, after the database copy. The destination has a database with thevectorextension turned on and a bucket, saved throughPUT /destinations.In the destination the
knowledge_baserow now sayspostgres, and the bucket holdsfiles/<user id>/cat.txt. In this instance's own database the same row still sayssqlite.A knowledge base whose vectors are not unit length is not copied until the admin accepts the change of ranking, which the next PR adds. Until then its step reads blocked:
Copy the database again, and the two copies after it are to be made again:
How I tested it
The two new files hold 69 cases at this layer. At the top of the stack, with the fixes of every layer in place, the six test files of the migration (routes, pause, copy runs, copies, preflight and knowledge base relocation) give 417 passed and 16 skipped with no service configured, and the copy runs file gives 61 passed and 3 skipped against a local PostgreSQL with pgvector and no S3 keys. I did not start an S3 server for this rebuild.
Every copy in the tests is the real command, run by the route as a child process against a real destination: a PostgreSQL database with pgvector and an S3 bucket of the test's own. The knowledge bases are made the way the app makes them, as SQLite stores with their chunks and vectors.
postgresand its vector table holds every chunk. This instance's row still sayssqlite. Then the database is copied again: the destination's row sayssqliteonce more, the step readscurrent, and copying the knowledge bases again puts it right.LANGFLOW_STORAGE_TYPE=s3. The file still lands in the bucket the admin named. A chat attachment recorded by its path on this instance's disk is renamed in the destination'smessage.files, and this instance's own row is unchanged.crashed, with the last lines of stderr as the message. This one needs no driver, so it runs in the unit job too.CONFIG_DIRand in no log.secrets_missingwhen the worker's keys are for another bucket than the saved one, and a knowledge base copy that was made is refused withlockedwhile the database copy before it is blocked again. Both started with a 202 on the published commit.postgresand records 36 chunks, and the destination has no table for it. The test run and the copy both list it as failed withkb_target_short, the step reads blocked, and a second copy skips the knowledge base that was copied and lists the other again. Without the change the test run reportedokwith the knowledge base skipped. The unit job covers the command line the page builds for both kinds of source (read by the command's own parser too), what the command does when no option is given, both places where the command skips, a store that cannot be read, the count rule on a SQLite store, and which codes get the hint line. Typed by hand against the same setup,langflow relocate-kb --to postgres --dry-runlists that knowledge base as failed, prints the hint under it and ends with exit code 1, and with--no-verify-skippedit lists it as skipped, prints no hint and ends with 0. That pgvector counts a table that is not there as 0 is checked only by the tests that need PostgreSQL.PGVECTOR_CONNECTION_STRINGnaming another database than the instance's own, the copy starts, and the environment of the real child, read from the process, carries that value for the vectors and the instance's own address for the database. Without the variable the step reads blocked withpgvector_env_missing, starting it answers 409 and no command starts. The same 409 answers when the step already reads done.The tests that need PostgreSQL or S3 skip when the driver or the server is missing. The S3 ones carry the
api_key_requiredmarker, like the other object storage tests.I saw every new test fail before the code existed. The rule about copying the database again came from a real run: I copied the database a second time on a real server and found the destination's knowledge base rows pointing back at local disk while the step still read done. The test for it failed in the same way before the fix.
Summary by CodeRabbit
--no-verify-skippedto skip it.