MCPcopy Create free account
hub / github.com/erans/pgsqlite / test_db_handler_concurrent_access

Function test_db_handler_concurrent_access

tests/connection_pool_test.rs:74–205  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

72
73#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
74async fn test_db_handler_concurrent_access() -> Result<(), Box<dyn std::error::Error>> {
75 // Use a temporary file for concurrent access
76 let temp_dir = tempfile::tempdir()?;
77 let db_path = temp_dir.path().join("test_concurrent.db");
78 let db_handler = Arc::new(DbHandler::new(db_path.to_str().unwrap())?);
79
80 // Create initial session for setup
81 let setup_session_id = Uuid::new_v4();
82 db_handler.create_session_connection(setup_session_id).await?;
83
84 // Create test table with AUTOINCREMENT to avoid conflicts
85 db_handler.execute_with_session("CREATE TABLE test_concurrent (id INTEGER PRIMARY KEY AUTOINCREMENT, thread_id INTEGER)", &setup_session_id).await?;
86
87 // Test concurrent reads (these should work fine)
88 let mut handles = vec![];
89
90 // First insert some test data
91 for i in 0..10 {
92 db_handler.execute_with_session(&format!("INSERT INTO test_concurrent (thread_id) VALUES ({i})"), &setup_session_id)
93 .await
94 .unwrap_or_else(|e| panic!("Failed to insert initial data {i}: {e:?}"));
95 }
96
97 // Add a small delay to ensure data is committed (helps with CI timing)
98 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
99
100 // Spawn multiple tasks for concurrent reads
101 // Use fewer concurrent tasks on CI to reduce resource pressure
102 let num_tasks = if std::env::var("CI").is_ok() { 3 } else { 5 };
103 let iterations_per_task = if std::env::var("CI").is_ok() { 5 } else { 10 };
104
105 for i in 0..num_tasks {
106 let db = db_handler.clone();
107 let task_iterations = iterations_per_task; // Capture for async block
108 let handle = tokio::spawn(async move {
109 // Create session for this task
110 let task_session_id = Uuid::new_v4();
111 db.create_session_connection(task_session_id).await
112 .expect("Failed to create session connection");
113
114 for j in 0..task_iterations {
115 // Retry logic for CI stability
116 let mut retry_count = 0;
117 let max_retries = if std::env::var("CI").is_ok() { 3 } else { 1 };
118
119 loop {
120 // Use COUNT to verify we have data (SELECT has a bug returning only 10 rows)
121 match db.query_with_session("SELECT COUNT(*) FROM test_concurrent", &task_session_id).await {
122 Ok(result) => {
123 // Verify we have at least 10 rows (our initial inserts)
124 if let Some(count_bytes) = &result.rows[0][0] {
125 let count_str = std::str::from_utf8(count_bytes).unwrap();
126 let count: i64 = count_str.parse().unwrap();
127 assert!(count >= 10, "Expected at least 10 rows, got {count}");
128 }
129 break;
130 }
131 Err(e) => {

Callers

nothing calls this directly

Calls 5

query_with_sessionMethod · 0.80
execute_with_sessionMethod · 0.45
cloneMethod · 0.45

Tested by

no test coverage detected