From 83739eeeb02f72d76214a3ee0500bf4cff893df9 Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Mon, 28 Oct 2019 11:08:05 +0300 Subject: [PATCH 01/14] feat: use AnyCable --- Gemfile | 7 +++++++ Gemfile.lock | 14 +++++++++++++ app/channels/application_cable/connection.rb | 8 ++++++- app/views/layouts/application.html.erb | 1 + config/application.rb | 2 ++ config/cable.yml | 11 ++++++---- config/environments/development.rb | 3 +++ docker-compose.yml | 22 ++++++++++++++++++++ 8 files changed, 63 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 0dcecef..b85d4a6 100644 --- a/Gemfile +++ b/Gemfile @@ -18,6 +18,9 @@ gem 'redis', '~> 4.0' # Use ActiveModel has_secure_password # gem 'bcrypt', '~> 3.1.7' +# Efficient ActionCable replacement to use web-sockets +gem 'anycable-rails', '~> 0.6' + # Use ActiveStorage variant # gem 'mini_magick', '~> 4.8' @@ -31,6 +34,10 @@ group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'pry-rails' + + # AnyCable Web Socket server + # Disabled. Gem is very unstable. + # gem "anycable-rack-server" end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 68490b6..e69c583 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -42,6 +42,13 @@ GEM i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) + anycable (0.6.3) + anyway_config (~> 1.4.2) + grpc (~> 1.17) + anycable-rails (0.6.4) + anycable (~> 0.6.0) + rails (>= 5) + anyway_config (1.4.4) arel (9.0.0) bindex (0.8.1) bootsnap (1.4.4) @@ -55,6 +62,12 @@ GEM ffi (1.11.1) globalid (0.4.2) activesupport (>= 4.2.0) + google-protobuf (3.9.2) + googleapis-common-protos-types (1.0.4) + google-protobuf (~> 3.0) + grpc (1.24.0) + google-protobuf (~> 3.8) + googleapis-common-protos-types (~> 1.0) i18n (1.6.0) concurrent-ruby (~> 1.0) jbuilder (2.9.1) @@ -153,6 +166,7 @@ PLATFORMS ruby DEPENDENCIES + anycable-rails (~> 0.6) bootsnap (>= 1.1.0) byebug jbuilder (~> 2.5) diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index dde95a7..5ab950c 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -3,8 +3,14 @@ class Connection < ActionCable::Connection::Base identified_by :current_user def connect - self.current_user = request.session.fetch("username", nil) + self.current_user = session.fetch("username", nil) reject_unauthorized_connection unless current_user end + + # By default we don't have access to the session object + # https://edgeguides.rubyonrails.org/action_cable_overview.html#notes + def session + cookies.encrypted[Rails.application.config.session_options[:key]] + end end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 839f820..2f9c6da 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -4,6 +4,7 @@ EvilChat <%= csrf_meta_tags %> <%= csp_meta_tag %> + <%= action_cable_meta_tag %> <%= stylesheet_pack_tag 'application', media: 'all' %> diff --git a/config/application.rb b/config/application.rb index ec8632f..b1bdc19 100644 --- a/config/application.rb +++ b/config/application.rb @@ -27,6 +27,8 @@ class Application < Rails::Application # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. + config.action_cable.url = ENV.fetch("CABLE_URL") { "ws://localhost:3334/cable" } + config.generators do |g| # Don't generate assets for Sprockets g.assets = nil diff --git a/config/cable.yml b/config/cable.yml index 1876ed7..ffc160f 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -1,10 +1,13 @@ +default: &default + adapter: <%= ENV.fetch('CABLE_ADAPTER', 'any_cable') %> + development: - adapter: async + <<: *default test: - adapter: async + <<: *default + channel_prefix: evil_chat_test production: - adapter: redis - url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + <<: *default channel_prefix: evil_chat_production diff --git a/config/environments/development.rb b/config/environments/development.rb index d52ec9e..5df2211 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -51,4 +51,7 @@ # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. config.file_watcher = ActiveSupport::EventedFileUpdateChecker + + # Always run gRPC server from anycable-rack-server alongside the app's server + # config.any_cable_rack.run_rpc = true end diff --git a/docker-compose.yml b/docker-compose.yml index 09fde98..753fa54 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -55,6 +55,10 @@ services: condition: service_healthy webpacker: condition: service_started + anycable-ws: + condition: service_started + anycable-rpc: + condition: service_started webpacker: <<: *app @@ -69,6 +73,24 @@ services: RAILS_ENV: ${RAILS_ENV:-development} WEBPACKER_DEV_SERVER_HOST: 0.0.0.0 + anycable-ws: + image: anycable/anycable-go:v0.6.4 + ports: + - '3334:3334' + environment: + PORT: 3334 + REDIS_URL: redis://redis:6379/0 + ANYCABLE_RPC_HOST: anycable-rpc:50051 + depends_on: + - anycable-rpc + - redis + + anycable-rpc: + <<: *backend + command: bundle exec anycable + ports: + - '50051' + postgres: image: postgres:12 volumes: From ccf46675a7bd2046dedbe086a19308010a22548b Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Mon, 28 Oct 2019 12:32:57 +0300 Subject: [PATCH 02/14] chore: prepare Heroku deployment --- Procfile | 2 +- bin/heroku-web | 7 +++++++ config/environments/production.rb | 2 +- config/master.key.back | 1 - 4 files changed, 9 insertions(+), 3 deletions(-) create mode 100755 bin/heroku-web delete mode 100644 config/master.key.back diff --git a/Procfile b/Procfile index 8f60e2a..ed02d6e 100644 --- a/Procfile +++ b/Procfile @@ -1 +1 @@ -server: bin/rails server +web: bin/heroku-web diff --git a/bin/heroku-web b/bin/heroku-web new file mode 100755 index 0000000..7d5b6a3 --- /dev/null +++ b/bin/heroku-web @@ -0,0 +1,7 @@ +#!/bin/bash + +if [ "$ANYCABLE_DEPLOYMENT" == "true" ]; then + bundle exec anycable --server-command="anycable-go" +else + bundle exec rails server -p $PORT -b 0.0.0.0 +fi diff --git a/config/environments/production.rb b/config/environments/production.rb index 6026643..371754e 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -16,7 +16,7 @@ # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). - config.require_master_key = true + # config.require_master_key = true # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. diff --git a/config/master.key.back b/config/master.key.back deleted file mode 100644 index 8b63c1e..0000000 --- a/config/master.key.back +++ /dev/null @@ -1 +0,0 @@ -533269e346eb9fd9dc4adc9807749c03 \ No newline at end of file From 8fc6fd7bf4d1d2a642d6fbc4c546b0afa80f541e Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Mon, 28 Oct 2019 15:14:12 +0300 Subject: [PATCH 03/14] chore: run db migrations on Heroku --- Procfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Procfile b/Procfile index ed02d6e..4a649d8 100644 --- a/Procfile +++ b/Procfile @@ -1 +1,2 @@ web: bin/heroku-web +release: bundle exec rails db:migrate From 6fb6e2f508b4e7fde70d208ca131d42d084c899b Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Mon, 28 Oct 2019 15:23:10 +0300 Subject: [PATCH 04/14] fix: check presence of session cookie --- app/channels/application_cable/connection.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index 5ab950c..dd3583a 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -10,7 +10,7 @@ def connect # By default we don't have access to the session object # https://edgeguides.rubyonrails.org/action_cable_overview.html#notes def session - cookies.encrypted[Rails.application.config.session_options[:key]] + cookies.encrypted[Rails.application.config.session_options[:key]] || {} end end end From 22f7599043ad9ae44d7ad3496d89358055624f33 Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Mon, 28 Oct 2019 23:20:12 +0300 Subject: [PATCH 05/14] chore: make action cable enabled by default --- config/application.rb | 2 +- config/cable.yml | 2 +- docker-compose.yml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/config/application.rb b/config/application.rb index b1bdc19..87f30ce 100644 --- a/config/application.rb +++ b/config/application.rb @@ -27,7 +27,7 @@ class Application < Rails::Application # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. - config.action_cable.url = ENV.fetch("CABLE_URL") { "ws://localhost:3334/cable" } + config.action_cable.url = ENV.fetch("CABLE_URL") { ENV["ANY_CABLE"] == "1" ? "ws://localhost:3334/cable" : nil } config.generators do |g| # Don't generate assets for Sprockets diff --git a/config/cable.yml b/config/cable.yml index ffc160f..0aa6246 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -1,5 +1,5 @@ default: &default - adapter: <%= ENV.fetch('CABLE_ADAPTER', 'any_cable') %> + adapter: <%= ENV.fetch("CABLE_ADAPTER") { ENV["ANY_CABLE"] == "1" ? "any_cable" : "async" } %> development: <<: *default diff --git a/docker-compose.yml b/docker-compose.yml index 753fa54..8f77012 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,6 +37,7 @@ services: REDIS_URL: redis://redis:6379/ WEBPACKER_DEV_SERVER_HOST: webpacker DISABLE_SPRING: 1 + ANY_CABLE: 1 depends_on: postgres: condition: service_healthy From 5cd649eb1513c485856eac787bc0f89afc91b162 Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Tue, 29 Oct 2019 00:03:18 +0300 Subject: [PATCH 06/14] chore: remove anycable-rack-server --- Gemfile | 4 ---- config/environments/development.rb | 3 --- 2 files changed, 7 deletions(-) diff --git a/Gemfile b/Gemfile index b85d4a6..f5c7efa 100644 --- a/Gemfile +++ b/Gemfile @@ -34,10 +34,6 @@ group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'pry-rails' - - # AnyCable Web Socket server - # Disabled. Gem is very unstable. - # gem "anycable-rack-server" end group :development do diff --git a/config/environments/development.rb b/config/environments/development.rb index 5df2211..d52ec9e 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -51,7 +51,4 @@ # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. config.file_watcher = ActiveSupport::EventedFileUpdateChecker - - # Always run gRPC server from anycable-rack-server alongside the app's server - # config.any_cable_rack.run_rpc = true end From 692e2faf5176e0572e1c4ae6994ac7cb270a3300 Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Tue, 29 Oct 2019 11:01:04 +0300 Subject: [PATCH 07/14] chore: add ability to start anycable for bare metal local development --- Procfile.dev | 1 + 1 file changed, 1 insertion(+) diff --git a/Procfile.dev b/Procfile.dev index ca3bc6b..432a2fd 100644 --- a/Procfile.dev +++ b/Procfile.dev @@ -1,2 +1,3 @@ server: bin/rails server assets: bin/webpack-dev-server +anycable: bundle exec anycable --server-command "anycable-go --port 3334" From 31333529688773d9be5bb590a25e109f3485bba6 Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Tue, 29 Oct 2019 11:42:18 +0300 Subject: [PATCH 08/14] chore: make AnyCable enabled by default for development --- config/application.rb | 2 -- config/cable.yml | 5 +++-- config/environments/development.rb | 2 ++ config/environments/production.rb | 2 ++ docker-compose.yml | 1 - 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/config/application.rb b/config/application.rb index 87f30ce..ec8632f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -27,8 +27,6 @@ class Application < Rails::Application # -- all .rb files in that directory are automatically loaded after loading # the framework and any gems in your application. - config.action_cable.url = ENV.fetch("CABLE_URL") { ENV["ANY_CABLE"] == "1" ? "ws://localhost:3334/cable" : nil } - config.generators do |g| # Don't generate assets for Sprockets g.assets = nil diff --git a/config/cable.yml b/config/cable.yml index 0aa6246..585eddf 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -1,11 +1,12 @@ default: &default - adapter: <%= ENV.fetch("CABLE_ADAPTER") { ENV["ANY_CABLE"] == "1" ? "any_cable" : "async" } %> + # List of the available adapters: async, any_cable + adapter: <%= ENV.fetch("CABLE_ADAPTER") { "any_cable" } %> development: <<: *default test: - <<: *default + adapter: async channel_prefix: evil_chat_test production: diff --git a/config/environments/development.rb b/config/environments/development.rb index d52ec9e..58e7633 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -51,4 +51,6 @@ # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. config.file_watcher = ActiveSupport::EventedFileUpdateChecker + + config.action_cable.url = (ENV.fetch("CABLE_ADAPTER") { "any_cable" } == "any_cable") ? ENV.fetch("CABLE_URL") { "ws://localhost:3334/cable" } : nil end diff --git a/config/environments/production.rb b/config/environments/production.rb index 371754e..982a4c3 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -82,4 +82,6 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + config.action_cable.url = (ENV.fetch("CABLE_ADAPTER") { "any_cable" } == "any_cable") ? ENV.fetch("CABLE_URL") : nil end diff --git a/docker-compose.yml b/docker-compose.yml index 8f77012..753fa54 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -37,7 +37,6 @@ services: REDIS_URL: redis://redis:6379/ WEBPACKER_DEV_SERVER_HOST: webpacker DISABLE_SPRING: 1 - ANY_CABLE: 1 depends_on: postgres: condition: service_healthy From d10e95bad2febd68b0f8014b77e740656ec39213 Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Tue, 29 Oct 2019 12:07:20 +0300 Subject: [PATCH 09/14] docs: update readme --- README.md | 26 ++++++++++++++++++-------- config/environments/development.rb | 4 +++- config/environments/production.rb | 4 +++- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index cb2e17f..81629e3 100644 --- a/README.md +++ b/README.md @@ -16,16 +16,26 @@ If you are looking for code that reflects application at the end of any part, ta - [part-2 branch](https://github.com/demiazz/evil_chat/tree/part-2) for the Part 2; - [part-3 branch](https://github.com/demiazz/evil_chat/tree/part-3) for the Part 3. -# Installation +# Development installation +## When using localhost machine + +```sh +cp config/database.yml.example config/database.yml + +bundle install +bin/rails db:migrate +yarn install +brew install hivemind +brew install anycable-go +hivemind Procfile.dev ``` -$ cp config/database.yml.example config/database.yml -$ bin/rails credentials:edit +## When using Docker Compose -$ bundle install -$ bin/rails db:migrate -$ yarn install -$ brew install hivemind -$ hivemind Procfile.dev +```sh +brew install bibendi/dip/dip +eval "$(dip console)" +provision +rails s ``` diff --git a/config/environments/development.rb b/config/environments/development.rb index 58e7633..2c940af 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -52,5 +52,7 @@ # routes, locales, etc. This feature depends on the listen gem. config.file_watcher = ActiveSupport::EventedFileUpdateChecker - config.action_cable.url = (ENV.fetch("CABLE_ADAPTER") { "any_cable" } == "any_cable") ? ENV.fetch("CABLE_URL") { "ws://localhost:3334/cable" } : nil + if ENV.fetch("CABLE_ADAPTER", "any_cable") == "any_cable" + config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:3334/cable") + end end diff --git a/config/environments/production.rb b/config/environments/production.rb index 982a4c3..e4b0663 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -83,5 +83,7 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - config.action_cable.url = (ENV.fetch("CABLE_ADAPTER") { "any_cable" } == "any_cable") ? ENV.fetch("CABLE_URL") : nil + if ENV.fetch("CABLE_ADAPTER", "any_cable") == "any_cable" + config.action_cable.url = ENV.fetch("CABLE_URL") + end end From f49e3a612ee94f73cf4025a2827d4bf1cddfb3fb Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Wed, 30 Oct 2019 22:09:57 +0300 Subject: [PATCH 10/14] chore: fix configs --- config/cable.yml | 12 ++++-------- config/environments/development.rb | 6 +++--- config/environments/production.rb | 5 +---- 3 files changed, 8 insertions(+), 15 deletions(-) diff --git a/config/cable.yml b/config/cable.yml index 585eddf..ed9318b 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -1,14 +1,10 @@ -default: &default - # List of the available adapters: async, any_cable - adapter: <%= ENV.fetch("CABLE_ADAPTER") { "any_cable" } %> - +# List of available adapters: async, any_cable development: - <<: *default + adapter: <%= ENV.fetch("CABLE_ADAPTER", "any_cable") %> test: - adapter: async - channel_prefix: evil_chat_test + adapter: test production: - <<: *default + adapter: <%= ENV.fetch("CABLE_ADAPTER", "any_cable") %> channel_prefix: evil_chat_production diff --git a/config/environments/development.rb b/config/environments/development.rb index 2c940af..4c18f46 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -52,7 +54,5 @@ # routes, locales, etc. This feature depends on the listen gem. config.file_watcher = ActiveSupport::EventedFileUpdateChecker - if ENV.fetch("CABLE_ADAPTER", "any_cable") == "any_cable" - config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:3334/cable") - end + config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:3334/cable").presence end diff --git a/config/environments/production.rb b/config/environments/production.rb index e4b0663..451817c 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -35,6 +35,7 @@ # Mount Action Cable outside main process or domain # config.action_cable.mount_path = nil # config.action_cable.url = 'wss://example.com/cable' + config.action_cable.url = ENV["CABLE_URL"].presence # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. @@ -82,8 +83,4 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - - if ENV.fetch("CABLE_ADAPTER", "any_cable") == "any_cable" - config.action_cable.url = ENV.fetch("CABLE_URL") - end end From ea84a075e9cd176bb7d3d4d1ecdbb1a724cd36a4 Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Fri, 1 Nov 2019 09:15:04 +0300 Subject: [PATCH 11/14] feat: add anycable.yml --- config/anycable.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 config/anycable.yml diff --git a/config/anycable.yml b/config/anycable.yml new file mode 100644 index 0000000..7fd6e98 --- /dev/null +++ b/config/anycable.yml @@ -0,0 +1,40 @@ +# gRPC server settings, anycable grpc server will listen +# websocket server at given host:port, usually Anycable server runs locally to ws server +# MUST BE in sync with ws-server setting -rpc=0.0.0.0:50051 +# rpc_host: "localhost:50051" + +# redis url +# MUST BE in sync with ws-server setting -redis=redis://localhost:6379/5 +# REM: Redis PubSub system doesn't use the database part of URI +# redis_url: "redis://localhost:6379/5" + +# redis_sentinels: +# - { host: 'localhost', port: 26379 } +# - { host: 'redis-1-2', port: 26379 } +# - { host: 'redis-1-3', port: 26379 } + +# anycable use single pubsub queue, this is queue name +# MUST BE in sync with ws-server setting -redis_channel=__anycable__ +# redis_channel: "__anycable__", + +#---------- ENVIRONMENT VARIABLES ---------- +# since Anycable config based on anyway_config (https://github.com/palkan/anyway_config), all Anycable settings, +# can be set or overridden through corresponding Environment variable. +# Ex: rpc_host is overridden by ANYCABLE_RPC_HOST, redis_url by ANYCABLE_REDIS_URL e.t.c Look in anyway_config for more details + +default: &default + rpc_host: <%= ENV.fetch("ANYCABLE_RPC_HOST", "localhost:50051") %> + log_grpc: false + log_file: nil + debug: false # Shortcut to enable GRPC logging and debug level + log_level: info + redis_channel: "__anycable__" + redis_sentinels: [] + +development: + <<: *default + redis_url: <%= ENV.fetch("REDIS_URL", "redis://localhost:6379/2") %> + +production: + <<: *default + redis_url: <%= ENV.fetch("REDIS_URL", "redis://localhost:6379/1") %> From d6cf3891ed6bdb3e8ca2b93a099ddd0bc69d770e Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Fri, 1 Nov 2019 09:57:03 +0300 Subject: [PATCH 12/14] chore: add comments for action_cable.url --- config/environments/development.rb | 1 + config/environments/production.rb | 3 +++ 2 files changed, 4 insertions(+) diff --git a/config/environments/development.rb b/config/environments/development.rb index 4c18f46..fac6855 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -54,5 +54,6 @@ # routes, locales, etc. This feature depends on the listen gem. config.file_watcher = ActiveSupport::EventedFileUpdateChecker + # Specify AnyCable WebSocket server URL to make JS client connect to it config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:3334/cable").presence end diff --git a/config/environments/production.rb b/config/environments/production.rb index 451817c..8c653ba 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -35,6 +37,7 @@ # Mount Action Cable outside main process or domain # config.action_cable.mount_path = nil # config.action_cable.url = 'wss://example.com/cable' + # Specify AnyCable WebSocket server URL to make JS client connect to it config.action_cable.url = ENV["CABLE_URL"].presence # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] From c46fdf71f5ee3e0de3b299ba9213bddcc6079dc6 Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Tue, 5 Nov 2019 12:15:52 +0300 Subject: [PATCH 13/14] chore: update anycable configs --- config/anycable.yml | 52 ++++++++++++------------------ config/cable.yml | 5 +-- config/environments/development.rb | 2 +- config/environments/production.rb | 2 +- docker-compose.yml | 6 ++-- 5 files changed, 30 insertions(+), 37 deletions(-) diff --git a/config/anycable.yml b/config/anycable.yml index 7fd6e98..f8d54a0 100644 --- a/config/anycable.yml +++ b/config/anycable.yml @@ -1,40 +1,30 @@ -# gRPC server settings, anycable grpc server will listen -# websocket server at given host:port, usually Anycable server runs locally to ws server -# MUST BE in sync with ws-server setting -rpc=0.0.0.0:50051 -# rpc_host: "localhost:50051" - -# redis url -# MUST BE in sync with ws-server setting -redis=redis://localhost:6379/5 -# REM: Redis PubSub system doesn't use the database part of URI -# redis_url: "redis://localhost:6379/5" - -# redis_sentinels: -# - { host: 'localhost', port: 26379 } -# - { host: 'redis-1-2', port: 26379 } -# - { host: 'redis-1-3', port: 26379 } - -# anycable use single pubsub queue, this is queue name -# MUST BE in sync with ws-server setting -redis_channel=__anycable__ -# redis_channel: "__anycable__", - -#---------- ENVIRONMENT VARIABLES ---------- -# since Anycable config based on anyway_config (https://github.com/palkan/anyway_config), all Anycable settings, -# can be set or overridden through corresponding Environment variable. -# Ex: rpc_host is overridden by ANYCABLE_RPC_HOST, redis_url by ANYCABLE_REDIS_URL e.t.c Look in anyway_config for more details - +# This file contains per-environment settings for AnyCable. +# +# Since AnyCable config is based on anyway_config (https://github.com/palkan/anyway_config), all AnyCable settings +# can be set or overridden through the corresponding environment variables. +# E.g., `rpc_host` is overridden by ANYCABLE_RPC_HOST, `debug` by ANYCABLE_DEBUG etc. +# +# Note that AnyCable recognizes REDIS_URL env variable for Redis pub/sub adapter. If you want to +# use another Redis instance for AnyCable, provide ANYCABLE_REDIS_URL variable. +# +# Read more about AnyCable configuration here: https://docs.anycable.io/#/ruby/configuration +# default: &default - rpc_host: <%= ENV.fetch("ANYCABLE_RPC_HOST", "localhost:50051") %> + # Turn on/off access logs ("Started..." and "Finished...") + access_logs_disabled: false + # This is the host and the port to run AnyCable RPC server on. + # You must configure your WebSocket server to connect to it, e.g.: + # $ anycable-go --rpc-host=":50051" + rpc_host: "127.0.0.1:50051" + # Whether to enable gRPC level logging or not log_grpc: false - log_file: nil - debug: false # Shortcut to enable GRPC logging and debug level - log_level: info + # Use the same channel name for WebSocket server, e.g.: + # $ anycable-go --redis-channel="__anycable__" redis_channel: "__anycable__" - redis_sentinels: [] development: <<: *default - redis_url: <%= ENV.fetch("REDIS_URL", "redis://localhost:6379/2") %> + redis_url: "redis://localhost:6379/1" production: <<: *default - redis_url: <%= ENV.fetch("REDIS_URL", "redis://localhost:6379/1") %> diff --git a/config/cable.yml b/config/cable.yml index ed9318b..8a279ad 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -1,4 +1,6 @@ -# List of available adapters: async, any_cable +# Make it possible to switch adapters by passing the CABLE_ADAPTER env variable. +# For example, you can use it fallback to the standard Action Cable in staging/review +# environments (by setting `CABLE_ADAPTER=redis`). development: adapter: <%= ENV.fetch("CABLE_ADAPTER", "any_cable") %> @@ -7,4 +9,3 @@ test: production: adapter: <%= ENV.fetch("CABLE_ADAPTER", "any_cable") %> - channel_prefix: evil_chat_production diff --git a/config/environments/development.rb b/config/environments/development.rb index fac6855..9407425 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -54,6 +54,6 @@ # routes, locales, etc. This feature depends on the listen gem. config.file_watcher = ActiveSupport::EventedFileUpdateChecker - # Specify AnyCable WebSocket server URL to make JS client connect to it + # Specify AnyCable WebSocket server URL to use by JS client config.action_cable.url = ENV.fetch("CABLE_URL", "ws://localhost:3334/cable").presence end diff --git a/config/environments/production.rb b/config/environments/production.rb index 8c653ba..d0bdb2d 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -37,7 +37,7 @@ # Mount Action Cable outside main process or domain # config.action_cable.mount_path = nil # config.action_cable.url = 'wss://example.com/cable' - # Specify AnyCable WebSocket server URL to make JS client connect to it + # Specify AnyCable WebSocket server URL to use by JS client config.action_cable.url = ENV["CABLE_URL"].presence # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] diff --git a/docker-compose.yml b/docker-compose.yml index 753fa54..ee98a08 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,7 +34,9 @@ services: EDITOR: vim RAILS_ENV: ${RAILS_ENV:-development} DATABASE_URL: postgres://postgres:postgres@postgres:5432 - REDIS_URL: redis://redis:6379/ + REDIS_URL: redis://redis:6379/0 + ANYCABLE_REDIS_URL: redis://redis:6379/0 + ANYCABLE_RPC_HOST: 0.0.0.0:50051 WEBPACKER_DEV_SERVER_HOST: webpacker DISABLE_SPRING: 1 depends_on: @@ -79,7 +81,7 @@ services: - '3334:3334' environment: PORT: 3334 - REDIS_URL: redis://redis:6379/0 + ANYCABLE_REDIS_URL: redis://redis:6379/0 ANYCABLE_RPC_HOST: anycable-rpc:50051 depends_on: - anycable-rpc From c24f4ea4790e696dc7e7b230f56381d6d146c293 Mon Sep 17 00:00:00 2001 From: Misha Merkushin Date: Fri, 8 Nov 2019 15:25:27 +0300 Subject: [PATCH 14/14] feat: use session in anycable --- Gemfile | 2 +- Gemfile.lock | 18 ++++++++++++------ app/channels/application_cable/connection.rb | 6 ------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gemfile b/Gemfile index f5c7efa..33b625a 100644 --- a/Gemfile +++ b/Gemfile @@ -19,7 +19,7 @@ gem 'redis', '~> 4.0' # gem 'bcrypt', '~> 3.1.7' # Efficient ActionCable replacement to use web-sockets -gem 'anycable-rails', '~> 0.6' +gem 'anycable-rails', '~> 0.6', github: "anycable/anycable-rails", branch: "feature/rack-middleware" # Use ActiveStorage variant # gem 'mini_magick', '~> 4.8' diff --git a/Gemfile.lock b/Gemfile.lock index e69c583..984f58b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,12 @@ +GIT + remote: https://github.com/anycable/anycable-rails.git + revision: 59ebcbf9033725637b08dee5cbd5e26891dfc354 + branch: feature/rack-middleware + specs: + anycable-rails (0.6.4) + anycable (~> 0.6.0) + rails (>= 5) + GEM remote: https://rubygems.org/ specs: @@ -45,9 +54,6 @@ GEM anycable (0.6.3) anyway_config (~> 1.4.2) grpc (~> 1.17) - anycable-rails (0.6.4) - anycable (~> 0.6.0) - rails (>= 5) anyway_config (1.4.4) arel (9.0.0) bindex (0.8.1) @@ -62,10 +68,10 @@ GEM ffi (1.11.1) globalid (0.4.2) activesupport (>= 4.2.0) - google-protobuf (3.9.2) + google-protobuf (3.10.1) googleapis-common-protos-types (1.0.4) google-protobuf (~> 3.0) - grpc (1.24.0) + grpc (1.25.0) google-protobuf (~> 3.8) googleapis-common-protos-types (~> 1.0) i18n (1.6.0) @@ -166,7 +172,7 @@ PLATFORMS ruby DEPENDENCIES - anycable-rails (~> 0.6) + anycable-rails (~> 0.6)! bootsnap (>= 1.1.0) byebug jbuilder (~> 2.5) diff --git a/app/channels/application_cable/connection.rb b/app/channels/application_cable/connection.rb index dd3583a..181bb61 100644 --- a/app/channels/application_cable/connection.rb +++ b/app/channels/application_cable/connection.rb @@ -6,11 +6,5 @@ def connect self.current_user = session.fetch("username", nil) reject_unauthorized_connection unless current_user end - - # By default we don't have access to the session object - # https://edgeguides.rubyonrails.org/action_cable_overview.html#notes - def session - cookies.encrypted[Rails.application.config.session_options[:key]] || {} - end end end