Ruby Rack: startup and teardown operations (Tokyo Cabinet connection)

前端 未结 2 1283
离开以前
离开以前 2021-01-14 08:36

I have built a pretty simple REST service in Sinatra, on Rack. It\'s backed by 3 Tokyo Cabinet/Table datastores, which have connections that need to be opened and closed. I

相关标签:
2条回答
  • 2021-01-14 08:40

    Have you considered using Sinatra's configure blocks to set up your connections?

    configure do
      Connection.initialize_for_development
    end
    
    configure :production do
      Connection.initialize_for_production
    end
    

    That's a pretty common idiom while using things like DataMapper with Sinatra

    Check out the "Configuration" section at http://www.sinatrarb.com/intro

    0 讨论(0)
  • 2021-01-14 08:58

    If you have other Rack middleware that depend on these connections (by way of a dependence on your model classes), then I wouldn't put the connection logic in Sinatra -- what happens if you rip out Sinatra and put in another endpoint?

    Since you want connection-per-application rather than connection-per-request, you could easily write a middleware that initialized and cleaned up connections (sort of the Guard Idiom as applied to Rack) and install it ahead of any other middleware that need the connections.

    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
    

    If you later decide you want connection-per-thread or connection-per-request, you can change this middleware to put the connection in the env Hash, but you'll need to change your models as well. Perhaps this middleware could set a connection variable in each model class instead of storing it internally? In that case, you might want to do more checking about the state of the connection in the at_exit hook because another thread/request might have closed it.

    0 讨论(0)
提交回复
热议问题