5

データベースURIが時間とともに変化するWSGIの下でFlaskアプリを提供しています。URI は 2 時間ごとに別のデータベースに切り替わります。その時間を使って、一方のデータベースがいっぱいになり、もう一方のデータベースがアプリのデータを提供しています。

スイッチオーバーが発生したときに、クライアントが次の要求で正しい (異なる) データベースを取得できるように、セッションを構成する最善の方法を見つけるのに苦労しています。私のテストでは、最上位でデータベースを初期化すると、スイッチオーバーが発生したときに、クライアントはまだ古いデータベースを指しているままになります。

ページ (インデックスなど) 自体の内部にセッションを設定することも考えましたが、面倒です。また、あまりにも多くのデータベース接続を開いたり閉じたりして放置するのが心配です。起動時に両方のセッションを初期化し、各ページ内の切り替え時にどちらを使用するかを選択することで、おそらく機能させることができると思います。それは非効率的なようで、もっと良い方法があると確信しています。

ヘルプ?!

~~~~~~~~~~

これは私が現在行っていることの一般的な考え方ですが、リクエスト間で URI を変更する方法はありません。最上位コードは 1 回だけ、または頻繁に実行されます。

if now.hour % 2:
    db_name = 'db1'
else:
    db_name = 'db2'

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://foo:poo@localhost:3306/%s" % db_name

def init_db(uri, **kwargs):
    engine = create_engine(uri, **kwargs)

    Base.metadata.create_all(bind=engine)

    global db_session
    db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
    Base.query = db_session.query_property()


init_db(app.config['SQLALCHEMY_DATABASE_URI'], pool_recycle=3600)

@app.teardown_request
def shutdown_session(exception=None):
    db_session.remove()

@app.route('/')
def index():
    ...etc...

作業例 - 美しい。

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://foo:poo@localhost:3306/%s"

class SessionManager(object):
    def __init__(self, base_uri=None, **kwargs):
        self.session = None
        self.base_uri = base_uri
        self.kwargs = kwargs

    def get_session(self):
        if now.hour % 2:
            db_name = 'db1'
        else:
            db_name = 'db2'

        if self.session:
            if self.session.name == db_name:
                return self.session
            else:
                self.session.remove()
                self.session = None

        if not self.session:
            engine = create_engine(self.base_uri % db_name, **self.kwargs)
            db_session = scoped_session(sessionmaker(bind=engine))
            db_session.name = db_name
            self.session = db_session
        return db_session

session_manager = SessionManager(base_uri=app.config['SQLALCHEMY_DATABASE_URI'], pool_recycle=3600)

db_session = LocalProxy(session_manager.get_session)
4

1 に答える 1

4

ルールで指示されたときにエンジンとスコープ付きセッションを再作成するセッション用のカスタム ビルダーを作成できます。何かのようなもの

class SessionManager(object):

    def __init__(self):
        self.session = None

    def get_session(self):
        # return existing session or make a new engine and scoped_session

このクラスを透過的にするには、Werkzeug の LocalProxyを使用します。セッションを使用するコードはまったく変更する必要はありません。

session_manager = SessionManager()
db_session = LocalProxy(session_manager.get_session)
于 2013-01-24T09:51:12.253 に答える