aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpalkan <dementiev.vm@gmail.com>2017-07-06 17:34:05 +0300
committerpalkan <dementiev.vm@gmail.com>2017-07-06 17:34:05 +0300
commit2bce7777b70efe81f45e4ae8dc61b25f1e18771e (patch)
tree31ebb4f359bd8b604621d510b9c6944be4eecc96
parentc8ce3459648ce0f86646b564ce1c0bb16a4b48eb (diff)
downloadrails-2bce7777b70efe81f45e4ae8dc61b25f1e18771e.tar.gz
rails-2bce7777b70efe81f45e4ae8dc61b25f1e18771e.tar.bz2
rails-2bce7777b70efe81f45e4ae8dc61b25f1e18771e.zip
[Fix #28751] Hash stream long stream identifiers when using Postgres adapter
-rw-r--r--actioncable/CHANGELOG.md9
-rw-r--r--actioncable/lib/action_cable/subscription_adapter/postgresql.rb11
-rw-r--r--actioncable/test/subscription_adapter/common.rb14
3 files changed, 31 insertions, 3 deletions
diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md
index b1408496a0..fbe9863af7 100644
--- a/actioncable/CHANGELOG.md
+++ b/actioncable/CHANGELOG.md
@@ -1,3 +1,12 @@
+* Hash long stream identifiers when using Postgres adapter.
+
+ PostgreSQL has a limit on identifiers length (63 chars, [docs](https://www.postgresql.org/docs/current/static/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS)).
+ Provided fix minifies identifiers longer than 63 chars by hashing them with SHA1.
+
+ Fixes #28751.
+
+ *Vladimir Dementyev*
+
* ActionCable's `redis` adapter allows for other common redis-rb options (`host`, `port`, `db`, `password`) in cable.yml.
Previously, it accepts only a [redis:// url](https://www.iana.org/assignments/uri-schemes/prov/redis) as an option.
diff --git a/actioncable/lib/action_cable/subscription_adapter/postgresql.rb b/actioncable/lib/action_cable/subscription_adapter/postgresql.rb
index bdab5205ec..487564c46c 100644
--- a/actioncable/lib/action_cable/subscription_adapter/postgresql.rb
+++ b/actioncable/lib/action_cable/subscription_adapter/postgresql.rb
@@ -1,6 +1,7 @@
gem "pg", "~> 0.18"
require "pg"
require "thread"
+require "digest/sha1"
module ActionCable
module SubscriptionAdapter
@@ -12,16 +13,16 @@ module ActionCable
def broadcast(channel, payload)
with_connection do |pg_conn|
- pg_conn.exec("NOTIFY #{pg_conn.escape_identifier(channel)}, '#{pg_conn.escape_string(payload)}'")
+ pg_conn.exec("NOTIFY #{pg_conn.escape_identifier(channel_identifier(channel))}, '#{pg_conn.escape_string(payload)}'")
end
end
def subscribe(channel, callback, success_callback = nil)
- listener.add_subscriber(channel, callback, success_callback)
+ listener.add_subscriber(channel_identifier(channel), callback, success_callback)
end
def unsubscribe(channel, callback)
- listener.remove_subscriber(channel, callback)
+ listener.remove_subscriber(channel_identifier(channel), callback)
end
def shutdown
@@ -41,6 +42,10 @@ module ActionCable
end
private
+ def channel_identifier(channel)
+ channel.size > 63 ? Digest::SHA1.hexdigest(channel) : channel
+ end
+
def listener
@listener || @server.mutex.synchronize { @listener ||= Listener.new(self, @server.event_loop) }
end
diff --git a/actioncable/test/subscription_adapter/common.rb b/actioncable/test/subscription_adapter/common.rb
index 3aa88c2caa..80baf2f771 100644
--- a/actioncable/test/subscription_adapter/common.rb
+++ b/actioncable/test/subscription_adapter/common.rb
@@ -112,4 +112,18 @@ module CommonSubscriptionAdapterTest
assert_equal "two", queue.pop
end
end
+
+ def test_long_identifiers
+ channel_1 = "a" * 100 + "1"
+ channel_2 = "a" * 100 + "2"
+ subscribe_as_queue(channel_1) do |queue|
+ subscribe_as_queue(channel_2) do |queue_2|
+ @tx_adapter.broadcast(channel_1, "apples")
+ @tx_adapter.broadcast(channel_2, "oranges")
+
+ assert_equal "apples", queue.pop
+ assert_equal "oranges", queue_2.pop
+ end
+ end
+ end
end