3

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

我也有一些 Rack 中间件,比如 Warden,它们依赖于这些模型类。

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

谢谢!

4

2 回答 2

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上的“配置”部分

于 2010-04-06T14:00:30.810 回答
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挂钩中的连接状态,因为另一个线程/请求可能已经关闭了它。

于 2010-04-06T14:20:53.120 回答