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

Control maintenance mode via DB #48

Closed
jordmantheman opened this issue Jun 19, 2018 · 11 comments
Closed

Control maintenance mode via DB #48

jordmantheman opened this issue Jun 19, 2018 · 11 comments
Labels
enhancement New feature or request

Comments

@jordmantheman
Copy link

(feature request)

Using a text file on the host doesn't work for django installations that distribute requests across multiple hosts. It seems like more of a detriment of the library to avoid using tables for this control than a benefit. Are the maintainers philosophically against this, or was it just a more expensive implementation than the sentinel file approach?

@fabiocaccamo fabiocaccamo added the enhancement New feature or request label Jun 20, 2018
@fabiocaccamo
Copy link
Owner

fabiocaccamo commented Jun 20, 2018

@jordmantheman I know this limit, I thinks there could be 2 different ways to implement this new feature:

  • Implement a small model/admin internally to the lib.

  • Expose 2 new settings: MAINTENANCE_MODE_STATE_GETTER and MAINTENANCE_MODE_STATE_SETTER where it is possibile to define custom functions that implements the db read/write logic. This approach is the more flexible one.

@fabiocaccamo
Copy link
Owner

@jordmantheman which of the two options described above would you prefere?

@spapas
Copy link

spapas commented Nov 13, 2018

One extra thing to consider is to allow the users to use redis (if it is present for cache) instead of the database; querying redis for a true/false value is faster than querying the database.

The MAINTENANCE_MODE_STATE_GETTER you propose could probably be used for that (requiring the user to actually write the put/get code in the database) but I believe that it would be better to actually provide a buch of MAINTENANCE_MODE_STATE_GETTER for the user to use (probably two would be enough, one for the database and one for the redis backend similar to how django-constance backends work).

@jordmantheman
Copy link
Author

Sorry for the delay!

Having configurable setters/getters is probably best. Agree w/ @spapas that a couple of baked in implementations could be useful. Perhaps an implementation using django-cache (assuming an in-memory store isn't used) would be a useful abstraction for someone using redis.

@fabiocaccamo
Copy link
Owner

Added pluggable backends support in 0.12.0 version, enjoy :).

@fabiocaccamo
Copy link
Owner

Just implement your custom backend extending AbstractStateBackend:

import maintenance_mode.backends.AbstractStateBackend


class MaintenanceModeCustomBackend(AbstractStateBackend):

    def get_value(self):
		value = False
		# get the value here and return it
        return value

    def set_value(self, value):
        # store value
		pass

Then in settipgs.py set your custom backend class path:

MAINTENANCE_MODE_STATE_BACKEND = 'myapp.backends.MaintenanceModeCustomBackend'

@adremides
Copy link

Can please provide an example how to implmenent db way to switch maintenance mode on/off with a custom backend?

@fabiocaccamo
Copy link
Owner

@adremides you just need to:

  • create your own backend extending the abstract backend
  • override the get_value and set_value methods (to get and set the state value as you need)
  • set your backend as the default one using settings settings.MAINTENANCE_MODE_STATE_BACKEND

@adremides
Copy link

  • override the get_value and set_value methods (to get and set the state value as you need)

I have trouble figuring it out how to do that. How do I override those methods to write the value state to a field in the database?

@fabiocaccamo
Copy link
Owner

@adremides you can see existing backends to understand how to override a method.
Concerning how to read/write a model field value the django documentation is very good:

@adremides
Copy link

I will expand your instructions with an example of how I finally did this:

  • create your own backend extending the abstract backend:

    Inside of the app directory (in my case 'website'), create a folder called backends, inside of it create maintenance.py.

  • set your backend as the default one using settings settings.MAINTENANCE_MODE_STATE_BACKEND:

    In settings added MAINTENANCE_MODE_STATE_BACKEND = 'website.backends.maintenance.MaintenanceModeCustomBackend'

  • override the get_value and set_value methods (to get and set the state value as you need)

    My goal was to add maintenance mode in CodeRedCMS, so in the Settings area I created a new Category called
    MaintenanceModeSettings and inside of it a field called active (which is a Boolean):

# wagtailsettings_models.py
# ...
@register_setting(icon='fa-wrench')
class MaintenanceModeSettings(BaseSetting):
    """
    Maintenance Mode configuration.
    """
    class Meta:
        verbose_name = _('Maintenance Mode')

    active = models.BooleanField(
        default=False,
        verbose_name=_('Active'),
        help_text=_('Deactivate/Activate Maintenance Mode'),
    )

    panels = [
        MultiFieldPanel(
            [
                FieldPanel('active'),
            ],
            _('Maintenance Mode'),
        )
    ]
# ...

then I used this to override get_value

# maintenance.py
from maintenance_mode.backends import AbstractStateBackend
from wagtail.core.models import Site
from coderedcms.models.wagtailsettings_models import MaintenanceModeSettings


class MaintenanceModeCustomBackend(AbstractStateBackend):

    def get_value(self):
        maintenance_mode = MaintenanceModeSettings.for_site(
            Site.objects.get(is_default_site=True)
        ).active
        return maintenance_mode

    def set_value(self, value):
        raise NotImplementedError()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants