Source

django-storages / storages / backends / moka.py

The default branch has multiple heads

import os
import logging

from django.conf import settings
from queued_storage.backend import QueuedRemoteStorage
from redis import Redis  # depends on Redis server

# Get an instance of a logger
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

REDIS = getattr(settings, 'REDIS', None)


def upload_to(self, filename):
    """(Missing docstring)"""
    # workaround - cloudfiles backend currently suppresses '/'
    fullpath = unicode(os.path.join(self.path, filename)).\
        replace("/", "-")

    # another workaround: get rid of non ASCII-7 chars
    return u"".join(filter(lambda c: ord(c) <= 127, list(fullpath)))


class MokaStorage(QueuedRemoteStorage):
    """Moka custom storage."""

    def __init__(self):

        logger.info("Initializing storage: %s", self)

        super(MokaStorage, self).__init__(
            local='django.core.files.storage.FileSystemStorage',
            remote='storages.backends.mosso.CloudFilesStorage')

        self._redis = Redis(**settings.REDIS["storage"])
        logger.info("Connection to redis is now active: %s.", self._redis)

    def _get_local_storage(self, name):
        """Local storage retrieval."""

        if (self.local.exists(name)):
            if not self._redis.get(name):  # avoid firing multiple tasks
                logger.info("Scheduling upload task for file '%s'", name)
                self._send_task(name)

            else:
                logger.info("Not scheduling task for file '%s' "
                            "as it already ongoing.", name)

        else:
            # ok, here we're in trouble :-(
            logger.error(
                "File '%s' is missing from both local and remote resource", name
            )

        return self.local

    def get_cache_key(self, name):
        return '%s%s' % (self.cache_prefix, urllib.quote(name))


    def get_storage(self, name):
        """Storage retrieval."""

        if self._redis.sismember(settings.REMOTE, name):
            logger.info("Cache hit ok for file '%s'", name)
            return self.remote

        elif self._redis.sismember(settings.MISSING, name):
            logger.info(
                "File '%s' known to be missing from the remote resource. ",
                name
            )
            return self._get_local_storage(name)

        elif self.remote.exists(name):  # quite expensive
            logger.info("Caching remote storage for file '%s'.", name)
            self._redis.sadd(settings.REMOTE, name)
            return self.remote

        else:
            self._redis.sadd(settings.MISSING, name)
            logger.warning(
                "File '%s' was not found on the remote resource", name
            )
            return self._get_local_storage(name)