@@ -13,13 +13,16 @@ use ::usage_tracking::FunctionUsageTracker;
13
13
use cmd_util:: env:: env_config;
14
14
use common:: {
15
15
assert_obj,
16
- bootstrap_model:: index:: {
17
- database_index:: {
18
- DeveloperDatabaseIndexConfig ,
19
- IndexedFields ,
16
+ bootstrap_model:: {
17
+ index:: {
18
+ database_index:: {
19
+ DeveloperDatabaseIndexConfig ,
20
+ IndexedFields ,
21
+ } ,
22
+ IndexConfig ,
23
+ IndexMetadata ,
20
24
} ,
21
- IndexConfig ,
22
- IndexMetadata ,
25
+ schema:: SchemaState ,
23
26
} ,
24
27
db_schema,
25
28
document:: {
@@ -2445,3 +2448,72 @@ async fn test_subtransaction_failure_rolls_back_table_creation(
2445
2448
assert ! ( !TableModel :: new( & mut tx) . table_exists( TableNamespace :: test_user( ) , & table_name) ) ;
2446
2449
Ok ( ( ) )
2447
2450
}
2451
+
2452
+ // regression test for ENG-8184
2453
+ #[ convex_macro:: test_runtime]
2454
+ async fn test_schema_registry_takes_read_dependency ( rt : TestRuntime ) -> anyhow:: Result < ( ) > {
2455
+ let db = DbFixtures :: new ( & rt) . await ?. db ;
2456
+ let nonexistent_schema_id = {
2457
+ // create an ID for a schema document that doesn't exist
2458
+ let mut tx = db. begin_system ( ) . await ?;
2459
+ SchemaModel :: new ( & mut tx, TableNamespace :: Global )
2460
+ . submit_pending ( db_schema ! ( ) )
2461
+ . await ?
2462
+ . 0
2463
+ } ;
2464
+
2465
+ // Create a transaction that does a by-id lookup on schemas & also observes the
2466
+ // lack of a pending schema
2467
+ let mut read_pending_tx = db. begin_system ( ) . await ?;
2468
+ assert ! ( read_pending_tx. get( nonexistent_schema_id) . await ?. is_none( ) ) ;
2469
+ assert ! (
2470
+ SchemaModel :: new( & mut read_pending_tx, TableNamespace :: Global )
2471
+ . get_by_state( SchemaState :: Pending )
2472
+ . await ?
2473
+ . is_none( )
2474
+ ) ;
2475
+ let read_pending_token = read_pending_tx. into_token ( ) ?;
2476
+
2477
+ // Now create a pending schema
2478
+ let schema_id;
2479
+ {
2480
+ let mut tx = db. begin_system ( ) . await ?;
2481
+ schema_id = SchemaModel :: new ( & mut tx, TableNamespace :: Global )
2482
+ . submit_pending ( db_schema ! ( ) )
2483
+ . await ?
2484
+ . 0 ;
2485
+ db. commit ( tx) . await ?;
2486
+ }
2487
+
2488
+ // The earlier read should be invalidated.
2489
+ assert_eq ! (
2490
+ db. refresh_token( read_pending_token, * db. now_ts_for_reads( ) )
2491
+ . await ?,
2492
+ None
2493
+ ) ;
2494
+
2495
+ // Now test the converse: create a transaction that observes the presence of
2496
+ // the pending schema.
2497
+ let mut read_pending_again_tx = db. begin_system ( ) . await ?;
2498
+ assert ! (
2499
+ SchemaModel :: new( & mut read_pending_again_tx, TableNamespace :: Global )
2500
+ . get_by_state( SchemaState :: Pending )
2501
+ . await ?
2502
+ . is_some( )
2503
+ ) ;
2504
+ let read_pending_again_token = read_pending_again_tx. into_token ( ) ?;
2505
+ {
2506
+ let mut tx = db. begin_system ( ) . await ?;
2507
+ SchemaModel :: new ( & mut tx, TableNamespace :: Global )
2508
+ . mark_validated ( schema_id)
2509
+ . await ?;
2510
+ db. commit ( tx) . await ?;
2511
+ }
2512
+ // The read should again be invalidated as the schema is no longer pending.
2513
+ assert_eq ! (
2514
+ db. refresh_token( read_pending_again_token, * db. now_ts_for_reads( ) )
2515
+ . await ?,
2516
+ None
2517
+ ) ;
2518
+ Ok ( ( ) )
2519
+ }
0 commit comments