Skip to content

Commit c803418

Browse files
committed
Merge remote-tracking branch 'origin/master' into symbol-icons-configurable
2 parents 6666fac + 08b40db commit c803418

File tree

128 files changed

+1550
-1155
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+1550
-1155
lines changed

.github/workflows/make-and-test.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,4 @@ jobs:
108108
109109
- run: cd src && npm install -g pnpm
110110
- run: cd src && pnpm run make
111-
- run: source venv/bin/activate && cd src && pnpm run test || pnpm run test || pnpm run test
112-
- run: cd src && pnpm run depcheck
111+
- run: source venv/bin/activate && cd src && pnpm run test-github-ci

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# CoCalc
22

3+
[![Make all packages and run their tests](https://github.com/sagemathinc/cocalc/actions/workflows/make-and-test.yml/badge.svg)](https://github.com/sagemathinc/cocalc/actions/workflows/make-and-test.yml)
4+
35
#### <u>_**Co**_</u>_llaborative_ <u>_**Calc**_</u>_ulation_
46

57
CoCalc is web-based software that enables collaboration in research, teaching, and scientific publishing. It includes [Jupyter Notebooks](https://cocalc.com/features/jupyter-notebook), [Sage Worksheets](https://cocalc.com/features/sage), a [LaTeX Editor](https://cocalc.com/features/latex-editor) and a [Linux Terminal](https://cocalc.com/features/terminal) to help people work together in real time from different locations. It also has a [Computational Whiteboard](https://cocalc.com/features/whiteboard) for expressing and sharing ideas and running code. It is available for free and [can be upgraded for internet access, better hosting quality, and other features](https://cocalc.com/store). It can also be used for [teaching courses](https://cocalc.com/features/teaching) with flexible [course license options](https://cocalc.com/pricing/courses). It is also possible to run CoCalc [on your own infrastructure](https://cocalc.com/pricing/onprem).

src/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
"c": "LOGS=/tmp/ DEBUG='cocalc:*' ./scripts/c",
1818
"version-check": "pip3 install typing_extensions mypy || pip3 install --break-system-packages typing_extensions mypy && ./workspaces.py version-check && mypy scripts/check_npm_packages.py",
1919
"test-parallel": "unset DEBUG && pnpm run version-check && cd packages && pnpm run -r --parallel test",
20-
"test": "unset DEBUG && pnpm run version-check && ./workspaces.py test",
20+
"test": "unset DEBUG && pnpm run depcheck && pnpm run version-check && ./workspaces.py test",
21+
"test-github-ci": "unset DEBUG && pnpm run depcheck && pnpm run version-check && ./workspaces.py test --exclude=jupyter --retries=1",
2122
"depcheck": "cd packages && pnpm run -r --parallel depcheck",
2223
"prettier-all": "cd packages/",
2324
"local-ci": "./scripts/ci.sh",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { before, after } from "@cocalc/backend/conat/test/setup";
2+
import { createClusterNode } from "./util";
3+
import getPort from "@cocalc/backend/get-port";
4+
5+
beforeAll(before);
6+
7+
describe("adding a node times out if we can't connect to it, rather than trying forever", () => {
8+
it("tries to add a link to a node that doesn't exist", async () => {
9+
const { server } = await createClusterNode({
10+
clusterName: "cluster0",
11+
id: "1",
12+
});
13+
const port = await getPort();
14+
expect(async () => {
15+
await server.join(`localhost:${port}`, { timeout: 500 });
16+
}).rejects.toThrow("timeout");
17+
});
18+
});
19+
20+
afterAll(after);

src/packages/backend/conat/test/cluster/cluster-basics.test.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
pnpm test `pwd`/cluster-basics.test.ts
44
5-
65
*/
76

87
import {
@@ -26,6 +25,7 @@ import { sysApi } from "@cocalc/conat/core/sys";
2625
beforeAll(before);
2726

2827
jest.setTimeout(20000);
28+
2929
describe("create a cluster enabled socketio server and test that the streams update as they should", () => {
3030
let server, client;
3131
it("create a server with cluster support enabled", async () => {
@@ -562,4 +562,29 @@ describe("test automatic node discovery", () => {
562562
});
563563
});
564564

565+
describe("test the clusterIpAddress option", () => {
566+
it("create a server without explicit clusterIpAddress", async () => {
567+
const { server } = await createClusterNode({
568+
clusterName: "cluster0",
569+
id: "0",
570+
});
571+
572+
expect(server.options.clusterIpAddress).toBe(undefined);
573+
expect(server.address()).toBe(`http://localhost:${server.options.port}`);
574+
server.close();
575+
});
576+
577+
it("create a server with explicit clusterIpAddress", async () => {
578+
const { server } = await createClusterNode({
579+
clusterName: "cluster0",
580+
id: "0",
581+
clusterIpAddress: "127.0.0.1",
582+
});
583+
584+
expect(server.options.clusterIpAddress).toBe("127.0.0.1");
585+
expect(server.address()).toBe(`http://127.0.0.1:${server.options.port}`);
586+
server.close();
587+
});
588+
});
589+
565590
afterAll(after);

src/packages/backend/conat/test/cluster/cluster-sticky.test.ts

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@ describe("create cluster of two nodes, and verify that *sticky* subs properly wo
1616
({ server: server1, client: client1 } = await createClusterNode({
1717
clusterName: "cluster0",
1818
id: "1",
19-
systemAccountPassword: "squeamish",
19+
autoscanInterval: 100,
20+
longAutoscanInterval: 1000,
2021
}));
2122
client1b = server1.client();
2223
({ server: server2, client: client2 } = await createClusterNode({
2324
clusterName: "cluster0",
2425
id: "2",
25-
systemAccountPassword: "ossifrage",
26+
autoscanInterval: 100,
27+
longAutoscanInterval: 1000,
2628
}));
2729
await server1.join(server2.address());
2830
await server2.join(server1.address());
@@ -60,11 +62,11 @@ describe("create cluster of two nodes, and verify that *sticky* subs properly wo
6062

6163
it("send messages and note they all go to the same target -- next the hard case across the cluster", async () => {
6264
// NOTE: if we do this test without waiting for consistent state, it will definitely
63-
// fail sometimes, since server2 literally doesn't know enough about the servers yet,
65+
// fail sometimes, since server2 literally doesn't know enough about the servers yet,
6466
// so has to make a different choice. Services of course must account for the fact that
6567
// for the first moments of their existence, sticky routing can't work.
6668
await waitForConsistentState([server1, server2]);
67-
69+
6870
await client2.waitForInterest(subject);
6971
for (let i = 0; i < count; i++) {
7072
await client2.publish(subject, "hi");
@@ -73,6 +75,45 @@ describe("create cluster of two nodes, and verify that *sticky* subs properly wo
7375
expect(recv1 + recv1b).toEqual(2 * count);
7476
expect(recv1 * recv1b).toEqual(0);
7577
});
78+
79+
let server3, client3;
80+
it("add a third node", async () => {
81+
const { client, server } = await createClusterNode({
82+
clusterName: "cluster0",
83+
autoscanInterval: 100,
84+
longAutoscanInterval: 5000,
85+
id: "3",
86+
});
87+
server3 = server;
88+
client3 = client;
89+
await server1.join(server.address());
90+
});
91+
92+
it("waits for consistent state -- this verifies, e.g., that sticky state is equal", async () => {
93+
await waitForConsistentState([server1, server2, server3]);
94+
});
95+
96+
it("client connected to server3 also routes properly", async () => {
97+
const total = recv1 + recv1b;
98+
await client3.waitForInterest(subject);
99+
for (let i = 0; i < count; i++) {
100+
await client3.publish(subject, "hi");
101+
}
102+
await wait({ until: () => recv1 + recv1b >= total + count });
103+
expect(recv1 + recv1b).toEqual(total + count);
104+
expect(recv1 * recv1b).toEqual(0);
105+
});
106+
107+
it("client1 and client2 still route properly", async () => {
108+
const total = recv1 + recv1b;
109+
for (let i = 0; i < count; i++) {
110+
await client1.publish(subject, "hi");
111+
await client2.publish(subject, "hi");
112+
}
113+
await wait({ until: () => recv1 + recv1b >= total + 2 * count });
114+
expect(recv1 + recv1b).toEqual(total + 2 * count);
115+
expect(recv1 * recv1b).toEqual(0);
116+
});
76117
});
77118

78119
afterAll(after);

src/packages/backend/conat/test/cluster/node-discovery.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { isEqual } from "lodash";
1010

1111
beforeAll(before);
1212

13-
jest.setTimeout(10000);
13+
jest.setTimeout(20000);
1414
describe("test automatic node discovery (and forgetting)", () => {
1515
const nodes: { client; server }[] = [];
1616
const clusterName = "auto";

src/packages/backend/conat/test/cluster/pubsub.test.ts

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import {
99
addNodeToDefaultCluster,
1010
wait,
1111
delay,
12+
waitForConsistentState,
13+
defaultCluster,
1214
} from "@cocalc/backend/conat/test/setup";
1315
import { STICKY_QUEUE_GROUP } from "@cocalc/conat/core/client";
1416

@@ -27,10 +29,13 @@ describe("the most basic pub/sub test with a 2-node cluster", () => {
2729
sub = await client0.subscribe("cocalc");
2830
});
2931

30-
it("publish -- message is initially dropped with no receiver because interest doesn't propogate instantly", async () => {
31-
const { count } = await client1.publish("cocalc", "hi");
32-
expect(count).toBe(0);
33-
});
32+
// commenting this out, since it is impossible to robustly test in all cases,
33+
// since sometmes the subscription info can move very quickly and this publish
34+
// could be slow!
35+
// it("publish -- message is initially dropped with no receiver because interest doesn't propogate instantly", async () => {
36+
// const { count } = await client1.publish("cocalc", "hi");
37+
// expect(count).toBe(0);
38+
// });
3439

3540
it("publish after waiting for interest -- this works", async () => {
3641
await client1.waitForInterest("cocalc");
@@ -79,7 +84,7 @@ describe("same basic test, but in the other direction", () => {
7984
});
8085
});
8186

82-
describe("with three nodes and two subscribers with different queue group on distinct nodes", () => {
87+
describe("three nodes and two subscribers with different queue group on distinct nodes", () => {
8388
let client0, client1, client2, server2;
8489
it("get the clients", async () => {
8590
client0 = server.client();
@@ -116,7 +121,7 @@ describe("with three nodes and two subscribers with different queue group on dis
116121
expect(count).toBe(1);
117122
});
118123

119-
it("make a sticky sub from all nodes and see that all messages go to the same receiver, no matter which node we send from", async () => {
124+
it("make sticky subs from each node, and see that all messages go to the same receiver, no matter which node we send from", async () => {
120125
const sub0 = await client0.subscribe("sticky", {
121126
queue: STICKY_QUEUE_GROUP,
122127
});
@@ -150,20 +155,38 @@ describe("with three nodes and two subscribers with different queue group on dis
150155
await client2.waitForInterest("sticky");
151156

152157
for (let i = 0; i < 20; i++) {
153-
const { count } = await client2.publish("sticky");
158+
const { count } = await client2.publish("sticky", null);
154159
expect(count).toBe(1);
155160
}
156161
for (let i = 0; i < 20; i++) {
157-
const { count } = await client1.publish("sticky");
162+
const { count } = await client1.publish("sticky", null);
158163
expect(count).toBe(1);
159164
}
160165
for (let i = 0; i < 20; i++) {
161-
const { count } = await client0.publish("sticky");
166+
const { count } = await client0.publish("sticky", null);
167+
expect(count).toBe(1);
168+
}
169+
await wait({ until: () => n0 + n1 + n2 == 60 });
170+
expect(n0 * n1).toBe(0);
171+
expect(n0 * n2).toBe(0);
172+
expect(n1 * n2).toBe(0);
173+
expect(n0 + n1 + n2).toBe(60);
174+
175+
await waitForConsistentState(defaultCluster);
176+
177+
// add another node and test
178+
const server3 = await addNodeToDefaultCluster();
179+
const client3 = server3.client();
180+
await waitForConsistentState(defaultCluster);
181+
for (let i = 0; i < 20; i++) {
182+
const { count } = await client3.publish("sticky", null);
162183
expect(count).toBe(1);
163184
}
185+
await wait({ until: () => n0 + n1 + n2 == 80 });
164186
expect(n0 * n1).toBe(0);
165187
expect(n0 * n2).toBe(0);
166188
expect(n1 * n2).toBe(0);
189+
expect(n0 + n1 + n2).toBe(80);
167190
});
168191
});
169192

src/packages/backend/conat/test/core/services.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
connect,
99
delay,
1010
} from "@cocalc/backend/conat/test/setup";
11-
import { Client, type Message } from "@cocalc/conat/core/client";
11+
import type { Client, Message } from "@cocalc/conat/core/client";
1212
import { wait } from "@cocalc/backend/conat/test/util";
1313

1414
beforeAll(before);

src/packages/backend/conat/test/persist/cluster.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,13 @@ describe("test using multiple persist servers in a cluster", () => {
138138
expect(t.getAll()).toEqual(["x"]);
139139
openStreams1.push(t);
140140
}
141-
expect(openStreams0.length).toBeGreaterThan(1);
141+
expect(openStreams0.length).toBeGreaterThan(0);
142142
});
143143

144144
it("remove one persist server", async () => {
145145
persistServer1.close();
146146
// [ ] TODO: removing this delay leads to very consistent failures
147-
// involving data loss, but things should just be slower, never broken,
147+
// involving data loss, but things should just be slower, never broken,
148148
// on automatic failover.
149149
await delay(3000);
150150
});

0 commit comments

Comments
 (0)