Skip to content

Commit

Permalink
Migrate to AnyCable JS client
Browse files Browse the repository at this point in the history
  • Loading branch information
palkan committed Sep 29, 2021
1 parent c0b8ad8 commit 5ff9620
Show file tree
Hide file tree
Showing 10 changed files with 77 additions and 84 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@
/yarn-error.log
yarn-debug.log*
.yarn-integrity
dip.override.yml
1 change: 1 addition & 0 deletions dip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ version: '5.0'

environment:
RAILS_ENV: development
ANYCABLE_CLIENT_PATH: "./vendor/anycable-client" # use `dip.override.yml` to change the location

compose:
files:
Expand Down
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ x-backend: &backend
tty: true
volumes:
- .:/app:cached
- ${ANYCABLE_CLIENT_PATH}:/app/vendor/anycable-client
- rails_cache:/app/tmp/cache
- bundle:/usr/local/bundle
- node_modules:/app/node_modules
Expand Down Expand Up @@ -157,6 +158,7 @@ services:
- 3036
volumes:
- .:/app:cached
- ${ANYCABLE_CLIENT_PATH}:/app/vendor/anycable-client
- bundle:/usr/local/bundle
- node_modules:/app/node_modules
- packs:/app/public/packs
Expand Down
27 changes: 16 additions & 11 deletions frontend/controllers/chat_controller.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
import { Controller } from "stimulus";
import { createChannel } from "../utils/cable";
import cable from "../utils/cable";
import { Channel } from "@anycable/web";
import { currentUser } from "../utils/current_user";
import { isPreview as isTurboPreview } from '../utils/turbo';

class ChatChannel extends Channel {
static identifier = "ChatChannel";

speak(message) {
this.perform("speak", { message });
}
}

export default class extends Controller {
static targets = ["input", "messages", "placeholder"];

connect() {
if (isTurboPreview()) return;

const channel = "ChatChannel";
const id = this.data.get("id");
this.channel = createChannel(
{channel, id},
{
received: (data) => {
this.handleMessage(data);
},
}
);

this.channel = new ChatChannel({ id });
this.channel.on("message", (data) => this.handleMessage(data));

cable.subscribe(this.channel);
}

disconnect() {
Expand Down Expand Up @@ -61,6 +66,6 @@ export default class extends Controller {

if (!message) return;

this.channel.perform("speak", {message});
this.channel.speak(message);
}
}
43 changes: 11 additions & 32 deletions frontend/controllers/connection_controller.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Controller } from "stimulus";
import { createCable } from "../utils/cable";
import cable from "../utils/cable";
import { isPreview as isTurboPreview } from '../utils/turbo';

export default class extends Controller {
Expand All @@ -13,47 +13,25 @@ export default class extends Controller {
connect() {
if (isTurboPreview()) return;

this.connection = createCable().connection;
this.unbind = [];

if (!this.connection.webSocket) {
// Action Cable initializes a WebSocket connection lazily,
// let's "append" the open method to know when a socket becomes available
const origOpen = this.connection.open.bind(this.connection);
this.connection.open = () => {
origOpen.call();
this.monitor(this.connection.webSocket);
}
} else if (this.connection.isActive()) {
return this.handleOpen();
}
this.unbind.push(cable.on("connect", this.handleOpen));
this.unbind.push(cable.on("disconnect", this.handleClose));
this.unbind.push(cable.on("close", this.handleClose));

this.handleClose();
if (cable.state !== "connected") this.handleClose();
}

connectCable() {
if (!this.connection.webSocket) return this.connection.open();
if (cable.state !== "disconnected") return;

this.connection.monitor.reconnectAttempts = 2;
this.connection.monitor.start();
this.connection.open();
cable.connect();
}

disconnectCable() {
if (!this.connection.isActive()) return;

this.connection.monitor.stop();
this.connection.close();
}

monitor(socket) {
if (this.socket) {
this.socket.removeEventListener("open", this.handleOpen);
this.socket.removeEventListener("close", this.handleClose);
}
if (cable.state !== "connected") return;

this.socket = socket;
this.socket.addEventListener("open", this.handleOpen);
this.socket.addEventListener("close", this.handleClose);
cable.close();
}

toggleState(e) {
Expand All @@ -76,5 +54,6 @@ export default class extends Controller {

disconnect() {
this.active = false;
if (this.unbind) this.unbind.forEach((clbk) => clbk());
}
}
20 changes: 10 additions & 10 deletions frontend/controllers/list_controller.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
import { Controller } from "stimulus";
import { createChannel } from "../utils/cable";
import cable from "../utils/cable";
import { Channel } from "@anycable/web";
import { isPreview as isTurboPreview } from '../utils/turbo';
import { DELETE, PATCH } from "../utils/api";

class ListChannel extends Channel {
static identifier = "ListChannel";
}

export default class extends Controller {
static targets = ["items"];

connect() {
if (isTurboPreview()) return;

const channel = "ListChannel";
const id = this.data.get("id");
const workspace = this.data.get("workspace");

this.channel = createChannel(
{channel, id, workspace},
{
received: (data) => {
this.handleUpdate(data);
},
}
);
this.channel = new ListChannel({ id, workspace });
this.channel.on("message", (data) => this.handleUpdate(data));

cable.subscribe(this.channel);
}

disconnect() {
Expand Down
20 changes: 10 additions & 10 deletions frontend/controllers/workspace_controller.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
import { Controller } from "stimulus";
import { createChannel } from "../utils/cable";
import cable from "../utils/cable";
import { Channel } from "@anycable/web";
import { isPreview as isTurboPreview } from '../utils/turbo';

class WorkspaceChannel extends Channel {
static identifier = "WorkspaceChannel";
}

export default class extends Controller {
static targets = ["lists", "form"];

connect() {
if (isTurboPreview()) return;

const channel = "WorkspaceChannel";
const id = this.data.get("id");

this.channel = createChannel(
{channel, id},
{
received: (data) => {
this.handleUpdate(data);
},
}
);
this.channel = new WorkspaceChannel({ id });
this.channel.on("message", (data) => this.handleUpdate(data));

cable.subscribe(this.channel);
}

disconnect() {
Expand Down
17 changes: 3 additions & 14 deletions frontend/utils/cable.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,5 @@
import { createConsumer } from "@rails/actioncable";
import { createCable } from "@anycable/web";

let consumer;
let consumer = createCable({ logLevel: "debug" });

export const createCable = () => {
if (!consumer) {
consumer = createConsumer();
}

return consumer;
}

export const createChannel = (...args) => {
const consumer = createCable();
return consumer.subscriptions.create(...args);
};
export default consumer;
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"dependencies": {
"@anycable/web": "^0.1.0",
"@hotwired/turbo-rails": "^7.0.0-beta.5",
"@rails/actioncable": "6.0.2",
"@rails/ujs": "^6.0.3-4",
"@rails/webpacker": "^6.0.0-beta.5",
"autoprefixer": "^10.2.5",
Expand Down Expand Up @@ -29,6 +29,8 @@
]
},
"browserslist": [
"defaults"
"defaults",
"not IE 11",
"not dead"
]
}
24 changes: 19 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,20 @@
# yarn lockfile v1


"@anycable/core@^0.1.0":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@anycable/core/-/core-0.1.1.tgz#7228b368e0858d8f338cec60b237b6d442328dd6"
integrity sha512-LG7DYv9zZq53XM5Hgsxic5bkVbKtfIO5AZB86No5NJzpsW21DjGceyp+jLJaMjYOw9yzcqo5acG1cE7IRBirOg==
dependencies:
nanoevents "^6.0.0"

"@anycable/web@^0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@anycable/web/-/web-0.1.0.tgz#80535f66e5aa77fdfa90e4726a8ace3500f55249"
integrity sha512-qm5BLWKv6u/eA4t/621hz8QawcD4jiVc149Fn6uQNhUm5AoW+QON+QXYMW0iDauhnlK+CoI5kbdLPpY55ARh5w==
dependencies:
"@anycable/core" "^0.1.0"

"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658"
Expand Down Expand Up @@ -890,11 +904,6 @@
mkdirp "^1.0.4"
rimraf "^3.0.2"

"@rails/[email protected]":
version "6.0.2"
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.0.2.tgz#bcba9bcd6ee09a47c6628336e07399a68ca87814"
integrity sha512-vN78gohsXPlC5jxBHlmiwkUI9bv6SulcZaE72kAIg/G4ou+wTdiMWPJK1bf2IxUNf+sfOjhl+tbRmY4AzJcgrw==

"@rails/actioncable@^6.1.0":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.3.tgz#c8a67ec4d22ecd6931f7ebd98143fddbc815419a"
Expand Down Expand Up @@ -3962,6 +3971,11 @@ nan@^2.12.1:
resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.2.tgz#f5376400695168f4cc694ac9393d0c9585eeea19"
integrity sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==

nanoevents@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/nanoevents/-/nanoevents-6.0.0.tgz#82454023f448a1eab0df103df59d5813ac16035b"
integrity sha512-0ASElaiZR21yBjhmBiRboCXeNirfIVuiKIxikn6a3H/9zUL+q2HBq+4B3Cb2UdCctoGx5YSwxTXypslD/olJKA==

nanoid@^3.1.20, nanoid@^3.1.22:
version "3.1.22"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.22.tgz#b35f8fb7d151990a8aebd5aa5015c03cf726f844"
Expand Down

0 comments on commit 5ff9620

Please sign in to comment.