我正在开发一个小应用程序。发送任务后,用户可以接收到一系列状态消息——通过这种方式,人们可以了解性能是否成功。这可以通过 SSE 和 JS 事件订阅来实现。问题是事件分布和变量隔离——我从未使用过多租户。
每个用户都应该使用自己的应用程序实例。每个用户都应该收到自己的事件。
我知道如何实现身份验证机制以及如何为每个任务提供唯一 ID,但是如何在 Sinatra 应用程序中实现多租户?有许多宝石和食谱,但它们都是为 RoR 编写的。
我的应用程序提供 Asterisk 传真处理。它由两部分组成:第一个是 Sinatra 的路由处理程序,第二个是后端进程 - 它侦听 Asterisk 事件(AMI),还提供新的任务发送。
正如人们所说,仍然很难理解我的应用程序应该做什么,我将逐步描述它。
- 用户登录。
- 用户发送电话任务(例如传真)。它必须是异步过程,因为你永远不知道会发生什么:可能会很忙,可能会在第 5 秒、第 9 秒出现答案……等等。
- 因此,在此过程中,用户会收到描述正在发生的事情的消息(我们的后台进程与电话服务器通信)。
- 然而此时另一个用户用户正在登录并发送他自己的任务。两个用户都可以看到他们的私人事件流。
但这不会发生:用户看到 2 个事件流的混乱。那是我的问题。
实际上,我的任务与聊天室实现类似,不同之处在于人们不应该互相交谈。他们应该通过服务器与后台进程“交谈”。每个人都可以说“你好”,服务器将“你好”重定向到后台进程,然后从后台进程返回一个私有的答案流给所有者,这是异步发生的。在聊天室中,你可以对另一个好友说“你好”,你永远不知道你什么时候会收到答案,但服务器知道这个答案是你的——你会得到你的私人答案。
以下是片段:
class FaxServer < Sinatra::Base
...
post '/run' do
settings.backend_process.async.run(param1, param2)
end
...
end
class MyBackendProcess
def run(number, file)
if File.exist?(file) then
change_status("Calling attempt, please wait...")
$stream.async.send_action ...
end
...
def handle_event(event)
case
when event.name === "Newchannel"
change_status("New channel is created")
...
end
end
class StatusSender
include Celluloid
include Celluloid::Notifications
def send_status(message)
publish("status_event", "#{Time.now.strftime('%R:%S')} : #{message}")
end
end
class StatusObserver
include Celluloid
include Celluloid::Notifications
def initialize(server)
@server = server
subscribe "status_event", :status_event
end
def status_event(*args)
@server.settings.connections.each { |out| out << "event: #{args[0].to_s}\ndata: #{args[1]}\n\n" }
end
end
提前致谢。