Skip to content

Commit 3a583b1

Browse files
committed
Add experimental channel helper
This makes it possible for people to send context from the terminal to other processes, like a browser, then wait for the process to finish from the terminal before continuing. This is useful when a browser needs to be opened to finish something before allowing the terminal to continue, like authentication.
1 parent 68549a6 commit 3a583b1

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

  • gem/terminalwire-rails/lib/terminalwire

gem/terminalwire-rails/lib/terminalwire/rails.rb

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,81 @@
55

66
module Terminalwire
77
module Rails
8+
class Channel
9+
# Prefix used to for channel name to avoid conflicts.
10+
NAMESPACE = "terminalwire".freeze
11+
12+
# Length of random channel name.
13+
RANDOM_NAME_LENGTH = 32
14+
15+
# 5 minutes, which is really way too much time.
16+
TIMEOUT_SECONDS = 5 * 60
17+
18+
attr_reader :name, :server, :logger, :timeout
19+
20+
def initialize(name: self.class.random_name, server: self.class.server, logger: self.class.logger, timeout: TIMEOUT_SECONDS)
21+
@server = server
22+
@name = name
23+
@queue = Queue.new
24+
@logger = logger
25+
@timeout = timeout
26+
27+
yield self if block_given?
28+
end
29+
30+
def broadcast(message)
31+
@logger.info "ActiveExchange: Publishing #{message.inspect} to #{@name.inspect}"
32+
@server.broadcast(@name, message)
33+
end
34+
alias :publish :broadcast
35+
36+
def subscribe
37+
return if @queue.closed?
38+
@logger.info "ActiveExchange: Subscribed to #{@name.inspect}"
39+
@server.subscribe(@name, -> (message) { @queue << message })
40+
end
41+
42+
def read
43+
Timeout::timeout @timeout do
44+
subscribe
45+
@logger.debug "Queue: waiting"
46+
@queue.pop
47+
end
48+
ensure
49+
@logger.debug "Queue: closed"
50+
@queue.close
51+
end
52+
alias :pop :read
53+
54+
def to_param
55+
self.class.verifier.generate(@name, expires_in: @timeout)
56+
end
57+
58+
class << self
59+
def server
60+
ActionCable.server.pubsub
61+
end
62+
63+
def logger
64+
::Rails.logger
65+
end
66+
67+
def random_name
68+
[NAMESPACE, SecureRandom.hex(RANDOM_NAME_LENGTH)].join(":")
69+
end
70+
71+
# Use Rails' secret_key_base for signing
72+
def verifier
73+
@verifier ||= ActiveSupport::MessageVerifier.new(::Rails.application.secret_key_base)
74+
end
75+
76+
def from_param(...)
77+
new name: verifier.verify(...)
78+
end
79+
alias :find :from_param
80+
end
81+
end
82+
883
class Session
984
# JWT file name for the session file.
1085
FILENAME = "session.jwt"

0 commit comments

Comments
 (0)