Ruby Rack:启动和拆卸操作(Tokyo Cabinet连接)

时间:2010-04-06 05:28:54

标签: ruby connection sinatra rack tokyo-cabinet

我在Rack上的Sinatra中构建了一个非常简单的REST服务。它由3个Tokyo Cabinet / Table数据存储区支持,这些数据存储区具有需要打开和关闭的连接。我有两个用直接Ruby编写的模型类,目前只是连接,获取或放置他们需要的东西,然后断开连接。显然,这不会长期发挥作用。

我也有像Warden这样的Rack中间件依赖于这些模型类。

管理打开和关闭连接的最佳方法是什么?据我所知,Rack不提供启动/关闭挂钩。我想在env中插入一个提供TC / TT对象引用的中间件,但是我必须通过Sinatra将其传递给模型,这看起来效率也不高;这只会成为TC的每请求连接。我认为每服务器实例生命周期将是更合适的生命周期。

谢谢!

2 个答案:

答案 0 :(得分:3)

您是否考虑过使用Sinatra的configure块来建立连接?

configure do
  Connection.initialize_for_development
end

configure :production do
  Connection.initialize_for_production
end

使用像DataMapper和Sinatra

之类的东西时,这是一个非常常见的习惯用法

查看http://www.sinatrarb.com/intro

上的“配置”部分

答案 1 :(得分:2)

如果你有其他依赖于这些连接的Rack中间件(通过依赖你的模型类),那么我就不会把连接逻辑放在Sinatra中 - 如果你撕掉Sinatra并放入另一个端点?

由于想要每个应用程序的连接而不是每个请求的连接,您可以轻松编写初始化和清理连接的中间件(类似于应用于Rack的Guard Idiom)和将其安装在需要连接的任何其他中间件之前。

class TokyoCabinetConnectionManagerMiddleware
  class <<self
    attr_accessor :connection
  end

  def initialize(app)
    @app = app
  end

  def call(env)
    open_connection_if_necessary!
    @app.call(env)
  end

  protected

  def open_connection_if_necessary!
    self.class.connection ||= begin
      ... initialize the connection ..
      add_finalizer_hook!
    end
  end

  def add_finalizer_hook!
    at_exit do
      begin
        TokyoCabinetConnectionManagerMiddleware.connection.close!
      rescue WhateverTokyoCabinetCanRaise => e
        puts "Error closing Tokyo Cabinet connection. You might have to clean up manually."
      end
    end
  end
end

如果您以后决定需要每个线程的连接或每个请求的连接,您可以更改此中间件以将连接放在env Hash中,但您也需要更改模型。也许这个中间件可以在每个模型类中设置一个connection变量而不是在内部存储它?在这种情况下,您可能希望更多地检查at_exit挂钩中的连接状态,因为另一个线程/请求可能已将其关闭。