Skip to content

Commit 0bc1533

Browse files
authored
Merge pull request #1750 from tursodatabase/lucio/clean-up-schema-replica
sqld: schema db and replica fixes
2 parents 7ab5dc0 + 1f0c9df commit 0bc1533

File tree

5 files changed

+159
-2
lines changed

5 files changed

+159
-2
lines changed

libsql-server/src/rpc/proxy.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ impl Proxy for ProxyService {
635635
Ok(conn) => {
636636
if !conn.is_primary() {
637637
return Err(tonic::Status::failed_precondition(
638-
"cannot run schema migration against a replica",
638+
"cannot run schema migration against a replica from a replica",
639639
));
640640
}
641641

@@ -710,7 +710,7 @@ impl Proxy for ProxyService {
710710
Ok(conn) => {
711711
if !conn.is_primary() {
712712
return Err(tonic::Status::failed_precondition(
713-
"cannot run schema migration against a replica",
713+
"cannot run schema migration against a replica from a replica",
714714
));
715715
}
716716

libsql-server/src/rpc/replication/replication_log.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,14 @@ impl ReplicationLog for ReplicationLogService {
351351
let (logger, config, version, _, _) =
352352
self.logger_from_namespace(namespace, &req, false).await?;
353353

354+
// If we are a shared schema and serving externally (aka to embedded replica's) then
355+
// return an error.
356+
if config.is_shared_schema && !self.service_internal {
357+
return Err(tonic::Status::failed_precondition(
358+
"cannot replicate a shared schema db",
359+
));
360+
}
361+
354362
let session_hash = self.encode_session_token(version);
355363

356364
let response = HelloResponse {

libsql-server/tests/cluster/mod.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,32 @@ fn large_proxy_query() {
311311

312312
sim.run().unwrap();
313313
}
314+
315+
#[test]
316+
fn replicate_from_shared_schema() {
317+
let mut sim = Builder::new()
318+
.simulation_duration(Duration::from_secs(10000))
319+
.tcp_capacity(100000)
320+
.build();
321+
make_cluster(&mut sim, 1, true);
322+
323+
sim.client("client", async {
324+
let db = Database::open_remote_with_connector("http://primary:8080", "", TurmoilConnector)
325+
.unwrap();
326+
let conn = db.connect().unwrap();
327+
328+
conn.execute("create table test (x)", ()).await.unwrap();
329+
330+
let db = Database::open_remote_with_connector("http://replica0:8080", "", TurmoilConnector)
331+
.unwrap();
332+
let conn = db.connect().unwrap();
333+
334+
conn.execute_batch("select * from sqlite_master;")
335+
.await
336+
.unwrap();
337+
338+
Ok(())
339+
});
340+
341+
sim.run().unwrap();
342+
}

libsql-server/tests/cluster/schema_dbs.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,64 @@ fn schema_migration_basics() {
129129

130130
sim.run().unwrap();
131131
}
132+
133+
#[test]
134+
fn schema_migration_via_replica() {
135+
let mut sim = Builder::new()
136+
.simulation_duration(Duration::from_secs(1000))
137+
.build();
138+
make_cluster(&mut sim, 1, true);
139+
140+
sim.client("client", async {
141+
let http = Client::new();
142+
143+
assert!(http
144+
.post(
145+
"http://primary:9090/v1/namespaces/schema/create",
146+
json!({ "shared_schema": true })
147+
)
148+
.await
149+
.unwrap()
150+
.status()
151+
.is_success());
152+
assert!(http
153+
.post(
154+
"http://primary:9090/v1/namespaces/foo/create",
155+
json!({ "shared_schema_name": "schema" })
156+
)
157+
.await
158+
.unwrap()
159+
.status()
160+
.is_success());
161+
162+
{
163+
let db = Database::open_remote_with_connector(
164+
"http://schema.primary:8080",
165+
"",
166+
TurmoilConnector,
167+
)
168+
.unwrap();
169+
let conn = db.connect().unwrap();
170+
conn.execute("create table test (x)", ()).await.unwrap();
171+
}
172+
173+
{
174+
let db = Database::open_remote_with_connector(
175+
"http://schema.replica0:8080",
176+
"",
177+
TurmoilConnector,
178+
)
179+
.unwrap();
180+
let conn = db.connect().unwrap();
181+
conn.execute("select * from sqlite_master;", ())
182+
.await
183+
.unwrap();
184+
185+
conn.execute("create table foo (x)", ()).await.unwrap();
186+
}
187+
188+
Ok(())
189+
});
190+
191+
sim.run().unwrap();
192+
}

libsql-server/tests/embedded_replica/mod.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1637,3 +1637,62 @@ fn replicated_synced_frames_zero_when_no_data_synced() {
16371637

16381638
sim.run().unwrap();
16391639
}
1640+
1641+
#[test]
1642+
fn schema_db() {
1643+
let tmp_embedded = tempdir().unwrap();
1644+
let tmp_host = tempdir().unwrap();
1645+
let tmp_embedded_path = tmp_embedded.path().to_owned();
1646+
let tmp_host_path = tmp_host.path().to_owned();
1647+
1648+
let mut sim = Builder::new()
1649+
.simulation_duration(Duration::from_secs(1000))
1650+
.build();
1651+
1652+
make_primary(&mut sim, tmp_host_path.clone());
1653+
1654+
sim.client("client", async move {
1655+
let http = Client::new();
1656+
1657+
assert!(http
1658+
.post(
1659+
"http://primary:9090/v1/namespaces/schema/create",
1660+
json!({ "shared_schema": true })
1661+
)
1662+
.await
1663+
.unwrap()
1664+
.status()
1665+
.is_success());
1666+
assert!(http
1667+
.post(
1668+
"http://primary:9090/v1/namespaces/foo/create",
1669+
json!({ "shared_schema_name": "schema" })
1670+
)
1671+
.await
1672+
.unwrap()
1673+
.status()
1674+
.is_success());
1675+
1676+
let path = tmp_embedded_path.join("embedded");
1677+
let db = Database::open_with_remote_sync_connector(
1678+
path.to_str().unwrap(),
1679+
"http://schema.primary:8080",
1680+
"",
1681+
TurmoilConnector,
1682+
false,
1683+
None,
1684+
)
1685+
.await
1686+
.unwrap();
1687+
1688+
db.sync().await.unwrap_err();
1689+
1690+
let conn = db.connect().unwrap();
1691+
1692+
conn.execute("create table test (x)", ()).await.unwrap_err();
1693+
1694+
Ok(())
1695+
});
1696+
1697+
sim.run().unwrap();
1698+
}

0 commit comments

Comments
 (0)