Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for storing state in Redis #1397

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ Enables persistent mode in Flower.
When persistent mode is enabled, Flower saves its current state and reloads it upon restart.
This ensures that Flower retains its state and configuration across restarts.
Flower stores its state in a database file specified by the `db`_ option.
If `db` starts with `redis://`, Flower will use Redis as a backend for storing its state.

.. _port:

Expand Down
42 changes: 32 additions & 10 deletions flower/events.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import collections
import logging
import pickle
import shelve
import threading
import time
Expand All @@ -13,6 +14,11 @@
from tornado.ioloop import PeriodicCallback
from tornado.options import options

try:
import redis
except ImportError:
redis = None

logger = logging.getLogger(__name__)

PROMETHEUS_METRICS = None
Expand Down Expand Up @@ -125,21 +131,33 @@ def __init__(self, capp, io_loop, db=None, persistent=False,

self.db = db
self.persistent = persistent
self.redis_client = None
if self.persistent and self.db.startswith("redis://"):
if not redis:
raise ImportError('redis library is required')
self.redis_client = redis.Redis.from_url(self.db)
self.enable_events = enable_events
self.state = None
self.state_save_timer = None

if self.persistent:
logger.debug("Loading state from '%s'...", self.db)
state = shelve.open(self.db)
if state:
self.state = state['events']
state.close()

if state_save_interval:
self.state_save_timer = PeriodicCallback(self.save_state,
state_save_interval)

if self.redis_client:
logger.debug("Loading state from Redis...")
state = self.redis_client.get('flower_events')
if state:
self.state = pickle.loads(state)

if not self.redis_client:
logger.debug("Loading state from '%s'...", self.db)
state = shelve.open(self.db)
if state:
self.state = state['events']
state.close()

if not self.state:
self.state = EventsState(**kwargs)

Expand Down Expand Up @@ -195,10 +213,14 @@ def run(self):
time.sleep(try_interval)

def save_state(self):
logger.debug("Saving state to '%s'...", self.db)
state = shelve.open(self.db, flag='n')
state['events'] = self.state
state.close()
if self.redis_client:
logger.debug("Saving state to Redis...")
self.redis_client.set('flower_events', pickle.dumps(self.state))
else:
logger.debug("Saving state to '%s'...", self.db)
state = shelve.open(self.db, flag='n')
state['events'] = self.state
state.close()

def on_enable_events(self):
# Periodically enable events for workers
Expand Down