Глобальная блокировка записи SQLite в Docker - PullRequest
0 голосов
/ 17 февраля 2020

У меня есть приложение Flask, работающее в среде docker с двумя SQAlchemy базами данных:

  1. Postgres (на основе сети)
  2. Sqlite ( на основе файла)

Это моя docker-compose конфигурация, работающая на Linux VM в MacOS:

   services:    
      web:
        build:
          context: ./services/web
          dockerfile: Dockerfile-dev
        volumes:
          - './services/web:/usr/src/app'
        ports:
          - 5001:5000
        environment:
          - FLASK_ENV=development
          - APP_SETTINGS=project.config.DevelopmentConfig
          - DATABASE_URL=postgres://postgres:postgres@web-db:5432/web_dev 
          - DATABASE_TEST_URL=postgres://postgres:postgres@web-db:5432/web_test
          - DATABASE_INDEX_URL=sqlite:////usr/src/app/project/db/index/searchindex.db
          - SECRET_KEY=my_precious
        depends_on:  
          - web-db
          - redis

    worker-scraping:
        image: dev3_web
        restart: always
        volumes:
          - ./services/web:/usr/src/app
          - ./services/web/celery_logs:/usr/src/app/celery_logs
        command: celery worker -A celery_worker.celery --loglevel=DEBUG --logfile=celery_logs/worker_scraping.log -Q scraping
        environment:
          - CELERY_BROKER=redis://redis:6379/0
          - CELERY_RESULT_BACKEND=redis://redis:6379/0
          - FLASK_ENV=development
          - APP_SETTINGS=project.config.DevelopmentConfig
          - DATABASE_URL=postgres://postgres:postgres@web-db:5432/web_dev 
          - DATABASE_TEST_URL=postgres://postgres:postgres@web-db:5432/web_test
          - DATABASE_INDEX_URL=sqlite:////usr/src/app/project/db/index/searchindex.db
          - SECRET_KEY=my_precious
        depends_on:
          - web
          - redis
          - web-db
        links:
          - redis:redis
          - web-db:web-db

config.py

class DevelopmentConfig(BaseConfig):
    """Development configuration"""
    SECRET_KEY = os.environ.get('SECRET_KEY')
    #sqlalchemy
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
    SQLALCHEMY_DATABASE_INDEX_URI = os.environ.get('DATABASE_INDEX_URL')
    SQLALCHEMY_BINDS = {
    'db1': SQLALCHEMY_DATABASE_URI,
    'db2': SQLALCHEMY_DATABASE_INDEX_URI
    }
    CELERY_BROKER_URL = os.environ.get('CELERY_BROKER')
    CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND')
    CELERY_IMPORTS = ('project.api.routes.background',)

Мое sqlite соединение должно быть установлено с помощью celery фонового процесса, например так:

@celery.task(
    queue='scraping',
    default_retry_delay=30, 
    max_retries=3, 
    soft_time_limit=100000)
def scrape_allblogs():
    # celery worker -A celery_worker.celery --loglevel=INFO  -Q scraping
    blog_crawler = crawler(current_app.config.get('SQLALCHEMY_DATABASE_INDEX_URI'))
    blog_crawler.create_index_tables() #DONE once
    for pagelist in all_pagelists:
        blog_crawler.crawl([pagelist])

    return {'Status': 'Blogs indexing updated!'}

и вот как метод создания и заполнения базы данных Выше было определено:

searchengine.py

class crawler:
    # Initialize the crawler with the name of database
    def __init__(self, dbname):
        self.con = sqlite3.connect(
            dbname, 
            timeout=10)

    def __del__(self):
        self.con.close()

    def dbcommit(self):
        self.con.commit()

и, наконец, вот как я инициализирую приложение:

__init __. py

import os
# third party libs
from flask import Flask  
from flask_sqlalchemy import SQLAlchemy
from celery import Celery
from flask_migrate import Migrate
# background processes instance
celery = Celery(__name__, broker='redis://redis:6379/0')
# extensions
migrate = Migrate()


def create_app(script_info=None):
    from .api.models.base import db
    from .api import routes, models
    # instantiate the app
    app = Flask(__name__)
    # set config
    app_settings = os.getenv('APP_SETTINGS')
    app.config.from_object(app_settings)
    # set up extensions
    migrate.init_app(app, db)
    routes.init_app(app)
    models.init_app(app)
    celery.conf.update(app.config)
    # shell context for flask cli
    @app.shell_context_processor
    def ctx():
        return {'app': app, 'db': db}

    return app

Несмотря на объявление d1 и d2 в config.py, я только привязываю модели к моей базе данных Postgres (d1), поэтому далеко, потому что мне нужен только доступ к d2 на данном этапе разработки:

class User(db.Model):

    __tablename__ = 'users'
    __bind_key__ = 'db1'

Когда я поднимаю свои контейнеры, пустой файл searchindex.db создается по правильному пути, но я ' m получает следующую ошибку:

[2020-02-17 18:55:47,033: DEBUG/MainProcess] pidbox received method enable_events() [reply_to:None ticket:None]
[2020-02-17 18:55:47,062: ERROR/ForkPoolWorker-1] Task project.api.routes.background.scrape_allblogs[6b02fe39-a51c-4a5d-8ee8-13af3a15180e] raised unexpected: OperationalError('unable to open database file')
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/celery/app/trace.py", line 385, in trace_task
    R = retval = fun(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/celery/app/trace.py", line 648, in __protected_call__
    return self.run(*args, **kwargs)
  File "/usr/src/app/project/api/routes/background.py", line 905, in scrape_allblogs
    blog_crawler = crawler(current_app.config.get('SQLALCHEMY_DATABASE_INDEX_URI'))
  File "/usr/src/app/project/api/classifiers/nlp/searchengine.py", line 201, in __init__
    timeout=10)
sqlite3.OperationalError: unable to open database file

* 10 60 * Чего мне не хватает? Как разблокировать базу данных sqlite?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...