Skip to content

Commit ab27fa8

Browse files
authored
Add ScyllaDB module (testcontainers#861)
1 parent 90c537d commit ab27fa8

File tree

10 files changed

+228
-0
lines changed

10 files changed

+228
-0
lines changed

docs/modules/scylladb.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# ScyllaDB Module
2+
3+
[ScyllaDB](https://www.scylladb.com/) is a distributed NoSQL wide-column database for data-intensive apps that require high performance and low latency. It was designed to be compatible with Apache Cassandra while achieving significantly higher throughputs and lower latencies.
4+
5+
6+
7+
## Install
8+
9+
```bash
10+
npm install @testcontainers/scylladb --save-dev
11+
```
12+
13+
## Examples
14+
15+
<!--codeinclude-->
16+
[Connect:](../../packages/modules/scylladb/src/scylladb-container.test.ts) inside_block:connectWithDefaultCredentials
17+
<!--/codeinclude-->
18+
19+
<!--codeinclude-->
20+
[Insert & fetch data:](../../packages/modules/scylladb/src/scylladb-container.test.ts) inside_block:createAndFetchData
21+
<!--/codeinclude-->

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ nav:
6464
- RabbitMQ: modules/rabbitmq.md
6565
- Redis: modules/redis.md
6666
- Redpanda: modules/redpanda.md
67+
- ScyllaDB: modules/scylladb.md
6768
- Selenium: modules/selenium.md
6869
- Weaviate: modules/weaviate.md
6970
- Configuration: configuration.md

package-lock.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import type { Config } from "jest";
2+
import * as path from "path";
3+
4+
const config: Config = {
5+
preset: "ts-jest",
6+
moduleNameMapper: {
7+
"^testcontainers$": path.resolve(__dirname, "../../testcontainers/src"),
8+
},
9+
};
10+
11+
export default config;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "@testcontainers/scylladb",
3+
"version": "10.14.0",
4+
"license": "MIT",
5+
"keywords": [
6+
"scylladb",
7+
"testing",
8+
"docker",
9+
"testcontainers"
10+
],
11+
"description": "ScyllaDB module for Testcontainers",
12+
"homepage": "https://github.com/testcontainers/testcontainers-node#readme",
13+
"repository": {
14+
"type": "git",
15+
"url": "https://github.com/testcontainers/testcontainers-node"
16+
},
17+
"bugs": {
18+
"url": "https://github.com/testcontainers/testcontainers-node/issues"
19+
},
20+
"main": "build/index.js",
21+
"files": [
22+
"build"
23+
],
24+
"publishConfig": {
25+
"access": "public"
26+
},
27+
"scripts": {
28+
"prepack": "shx cp ../../../README.md . && shx cp ../../../LICENSE .",
29+
"build": "tsc --project tsconfig.build.json"
30+
},
31+
"dependencies": {
32+
"testcontainers": "^10.14.0"
33+
},
34+
"devDependencies": {
35+
"cassandra-driver": "^4.7.2"
36+
}
37+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { ScyllaContainer, StartedScyllaContainer } from "./scylladb-container";
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Client } from "cassandra-driver"; // Scylla uses Cassandra's driver in Node.js
2+
import { ScyllaContainer } from "./scylladb-container";
3+
4+
describe("ScyllaDB", () => {
5+
jest.setTimeout(240_000);
6+
7+
// connectWithDefaultCredentials {
8+
it("should connect and execute a query", async () => {
9+
const container = await new ScyllaContainer("scylladb/scylla:6.2.0").start();
10+
11+
const client = new Client({
12+
contactPoints: [container.getContactPoint()],
13+
localDataCenter: container.getDatacenter(),
14+
keyspace: "system",
15+
});
16+
17+
await client.connect();
18+
19+
const result = await client.execute("SELECT cql_version FROM system.local");
20+
expect(result.rows[0].cql_version).toBe("3.3.1");
21+
22+
await client.shutdown();
23+
await container.stop();
24+
});
25+
// }
26+
27+
// createAndFetchData {
28+
it("should create keyspace, a table, insert data, and retrieve it", async () => {
29+
const container = await new ScyllaContainer().start();
30+
31+
const client = new Client({
32+
contactPoints: [container.getContactPoint()],
33+
localDataCenter: container.getDatacenter(),
34+
});
35+
36+
await client.connect();
37+
38+
// Create the keyspace
39+
await client.execute(`
40+
CREATE KEYSPACE IF NOT EXISTS test_keyspace
41+
WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}
42+
`);
43+
44+
await client.execute("USE test_keyspace");
45+
46+
// Create the table.
47+
await client.execute(`
48+
CREATE TABLE IF NOT EXISTS test_keyspace.users (
49+
id UUID PRIMARY KEY,
50+
name text
51+
)
52+
`);
53+
54+
// Insert a record
55+
const id = "d002cd08-401a-47d6-92d7-bb4204d092f8"; // Fixed UUID for testing
56+
const username = "Test McTestinson";
57+
await client.execute("INSERT INTO test_keyspace.users (id, name) VALUES (?, ?)", [id, username]);
58+
59+
// Fetch and verify the record
60+
const result = await client.execute("SELECT * FROM test_keyspace.users WHERE id = ?", [id], { prepare: true });
61+
expect(result.rows[0].name).toEqual(username);
62+
63+
await client.shutdown();
64+
await container.stop();
65+
});
66+
// }
67+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { AbstractStartedContainer, GenericContainer, type StartedTestContainer } from "testcontainers";
2+
3+
const SCYLLA_PORT = 9042;
4+
5+
export class ScyllaContainer extends GenericContainer {
6+
constructor(image = "scylladb/scylla:6.2.0") {
7+
super(image);
8+
this.withExposedPorts(SCYLLA_PORT);
9+
this.withCommand(["--skip-wait-for-gossip-to-settle=0"]);
10+
}
11+
12+
public override async start(): Promise<StartedScyllaContainer> {
13+
this.withEnvironment({
14+
SCYLLA_LISTEN_ADDRESS: "0.0.0.0",
15+
SCYLLA_BROADCAST_ADDRESS: "0.0.0.0",
16+
SCYLLA_RPC_ADDRESS: "0.0.0.0",
17+
});
18+
const startedContainer = await super.start();
19+
return new StartedScyllaContainer(startedContainer);
20+
}
21+
}
22+
23+
export class StartedScyllaContainer extends AbstractStartedContainer {
24+
private readonly port: number;
25+
26+
constructor(startedTestContainer: StartedTestContainer) {
27+
super(startedTestContainer);
28+
this.port = startedTestContainer.getMappedPort(SCYLLA_PORT);
29+
}
30+
31+
public getPort(): number {
32+
return this.port;
33+
}
34+
35+
public getDatacenter(): string {
36+
return "datacenter1"; // Forced in docker.
37+
}
38+
39+
public getContactPoint(): string {
40+
return `${this.getHost()}:${this.getPort()}`;
41+
}
42+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"extends": "./tsconfig.json",
3+
"exclude": [
4+
"build",
5+
"jest.config.ts",
6+
"src/**/*.test.ts"
7+
],
8+
"references": [
9+
{
10+
"path": "../../testcontainers"
11+
}
12+
]
13+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"extends": "../../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"rootDir": "src",
5+
"outDir": "build",
6+
"paths": {
7+
"testcontainers": [
8+
"../../testcontainers/src"
9+
]
10+
}
11+
},
12+
"exclude": [
13+
"build",
14+
"jest.config.ts"
15+
],
16+
"references": [
17+
{
18+
"path": "../../testcontainers"
19+
}
20+
]
21+
}

0 commit comments

Comments
 (0)