• Как установить activePicker в кастомном компоненте на основе v-date-picker?

    @alenov Автор вопроса
    Программист
    Сделал так, работает:

    <template>
      <v-menu
        v-model="menu"
        :close-on-content-click="false"
        :nudge-right="40"
        transition="scale-transition"
        offset-y
        min-width="auto"
      >
        <template v-slot:activator="{ on, attrs }">
          <v-text-field
            :value="valueInput"
            :label="label"
            :placeholder="placeholder"
            :hint="hint"
            prepend-icon="mdi-calendar"
            readonly
            dense
            v-bind="attrs"
            v-on="on"
          ></v-text-field>
        </template>
        <v-date-picker
          v-model="pickerInput"
          no-title
          :max="maxValue"
          :min="minValue"
          :show-current="showCurrent"
          @input="menu = false"
          :active-picker="activePicker"
        ></v-date-picker>
      </v-menu>
    </template>
    
    <script>
    import { formatDate } from "@/functions"
    // В параметре date в родительском компоненте нужно использовать модификатор .sync
    export default {
      name: "DatePicker",
      props: ['date', 'label', 'hint', 'min', 'max', 'showCurrent', 'placeholder', 'picker'],
      data () {
        return {
          menu: false,
          activePicker: null
        }
      },
      watch: {
        menu (val) {
          val && setTimeout(() => (this.activePicker = this.picker || 'DATE'))
        }
      },
      computed: {
        valueInput: {
          set (newValue) {
            this.$emit('update:date', newValue)
          },
          get: function() {
            return formatDate(this.date)
          }
        },
        pickerInput: {
          set (newValue) {
            this.$emit('update:date', newValue)
          },
          get: function() {
            return this.date
          }
        },
        minValue () {
          return this.min || null
        },
        maxValue () {
          return this.max || null
        }
      }
    }
    </script>
    Ответ написан
    Комментировать
  • Как в Python 3.5 обойти ошибку "ascii codec can`t decode..." при чтении из файла?

    @alenov Автор вопроса
    Программист
    Разобрался. Нужно было явно указать кодировку файла:
    with open(filename, 'r', encoding="utf-8") as f:
    Непонятно, почему в среде разработки это не имело значения...
    Ответ написан
  • Как в Vue-приложении сначала загрузить данные в $store, а уже потом рендерить шаблоны?

    @alenov Автор вопроса
    Программист
    Покопался с роутером, как советовал Игорь , и решил задачу через глобальный хук beforeEach. Получилось кратко, красиво, и в одном месте.
    router/index.js
    import store from '@/store'
    import axios from 'axios'
    ...
    router.beforeEach((to, from, next) => {
      if (!store.state.Data) {
        axios.post('https://site.ru/get_data').then(response => {
            store.dispatch('setData', response.data.Data)
            next()
      } else {
        next()
      }
    })


    Теперь переход на страницу выполняется только в случае, если данные загружены, а если не загружены - предварительно загружаются. Можно забыть про проверку наличия данных в компонентах.
    Ответ написан
    Комментировать
  • Как масштабировать сервис хранения картинок?

    @alenov Автор вопроса
    Программист
    Спасибо всем, кто дал полезные советы по существу вопроса. Ещё раз кратко. Имеется микросервис хранения картинок, который нужно масштабировать.
    Решение получилось следующим. Микросервис поднимается на нескольких серверах:
    s1.site.ru
    s2.site.ru
    s3.site.ru

    Также поднимается nginx-балансировщик s.site.ru:

    # Список серверов для балансировки запросов на запись (upload).
    upstream storage_backend {
        server s1.site.ru:80;
        server s2.site.ru:80;
        server s3.site.ru:80;
    }
    
    # Определение локации сервера для запросов на запись и удаление файла. Опция default нужна
    # только для того, чтобы в случае неопределённого запроса получить 404, а не 500.
    map $uri $storage_location {
        "~/(storage|delete)/s1-"  "s1.site.ru:80";
        "~/(storage|delete)/s2-"  "s2.site.ru:80";
        "~/(storage|delete)/s3-"  "s3.site.ru:80";
        default                           "s1.site.ru:80";
    }
    
    server {
        listen 80;
        server_name s.site.ru;
    
        location / {
            proxy_pass http://$storage_location;
        }
    
        location /upload/ {
            proxy_pass http://storage_backend;
        }
    
    }


    В блоке map часть паттерна "s1...s2...s3" - это префикс имени файла, который формируется и возвращается сервером, выполнившим запрос на запись. Т.е. сервер, записывающий файл, цепляет к имени префикс, по которому затем в этом блоке можно будет однозначно определить локацию. Это добавляет лишних хлопот при добавлении нового сервиса в пул: нужно "ручками" назначить ему этот префикс так, чтобы он был уникальным. Есть в этом какая-то неровность, но я не знаю в данный момент способа это обойти.

    В итоге при поступлении запросов на запись, типа POST s.site.ru/upload балансировщик выбирает очередной сервер из storage_backend, а при запросах на получение по uri определяет локацию по $storage_location.

    Ну и ssl прикручивается только к балансировщику, стандартно.

    Сделал небольшой тестовый пул локально, всё работает. Буду пробовать на реальном железе.
    Ответ написан
    Комментировать
  • Как грамотно организовать Backup файлового сервера и рабочих станций в небольшой организации?

    @alenov
    Программист
    Была аналогичная задача. Небольшая фирма (~30 чел), один сервер на win2000, остальные либо тонкие, либо толстые клиенты.
    Я ставил отдельный linux-сервер, на нём поднимал BackupPC и бэкапил сервак. Изумительная штука, много раз выручала возможность поднять нужную версию файла на конкретный день в прошлом. Легко и гибко настраивается. Отдельных толстых клиентов (бух, финансист) бэкапил отдельными потоками. Не было задач, которые не решались. Может бэкапить через инет.
    Ответ написан
    Комментировать
  • Как установить страницу по умолчанию в nginx?

    @alenov Автор вопроса
    Программист
    Нашёл причину. Не указал конечный слэш в инструкции, нужно так:
    proxy_pass                          http://localhost:5000/;


    Всё заработало.
    Всем спасибо!
    Ответ написан
    Комментировать
  • Как тестировать сервис А, который обращается к сервису Б, не поднимая локально сервиса Б (Python, Flask)?

    @alenov Автор вопроса
    Программист
    Решил задачу условным импортированием.

    import importlib
    
    def auth(fn):
        @wraps(fn)
        def wrapper(*args, **kwargs):
            # В переменной конфигурации EXT_API_MODULE хранится имя модуля, который содержит класс extAPI
            # для генерации вызовов к внешним API. Модулей два: ext_api.py и exp_api_test.py
            # В первом реальные обработчики для продакшена, EXT_API_MODULE="exp_api"
            # Во втором - заглушки для тестов, EXT_API_MODULE="exp_api_test"
            ext_api = importlib.import_module('application.{0}'.format(current_app.config['EXT_API_MODULE']))
            token = request.headers.get('X-Auth-Token')
            if not get_from_cache(token):
                res = ext_api.extAPI().auth_service(token)
                if res.status_code == 200:
                    set_to_cache(token)
                    return fn(*args, **kwargs)
    
                return Responce('{"error": "Invalid token"}', status=404)
    
        return wrapper


    Всем спасибо за участие!
    Ответ написан
    Комментировать
  • Почему прямая ссылка на сайт работает, а при проксировании через proxy_pass - нет?

    @alenov Автор вопроса
    Программист
    Разобрался. Нужно было явно установить заголовок Host:
    proxy_set_header Host api.site.ru
    Ответ написан
    Комментировать
  • Можно ли настроить проксирование в nginx, анализируя метод заголовка: GET, POST...?

    @alenov Автор вопроса
    Программист
    Кажется, что-то есть по этому вопросу.
    Есть переменная $request_method, по ней можно выполнять балансировку. Пробую такую конфигурацию:

    upstream master {
        server unix:/tmp/flask.sock;
    }
    
    upstream read_api {
        server api.service.ru;
    }
    
    map $request_method $upstream_location {
        GET         read_api;
        default     master;
    }
    
    server {
        listen 80;
        server_name service.ru;
    
        root /home/web/service;
        include uwsgi_params;
        include proxy_params;
    
        location / {
            if ($http_referer !~* ^($|http://) ){
                 return 403;
            }
            uwsgi_pass unix:/tmp/flask.sock;
        }
    
        location /restapi/v1/ {
            if ($upstream_location = "master") {
                uwsgi_pass unix:/tmp/flask.sock;
            }
            if ($upstream_location != "master") {
                proxy_pass https://$upstream_location;
            }
        }
    }

    Работает. Возможно, есть другой путь. Если кто-то подскажет - буду признателен.
    Ответ написан
    Комментировать
  • Почему комп на материнской плате ASUS TUF B360M-E GAMING просыпается от любого чиха?

    @alenov Автор вопроса
    Программист
    Спасибо всем за то, что подсказали правильное направление. Настройки Wake Up лежат в операционке. В моём случае - Linux Mint.
    Решается так (в моей конфигурации: USB-мышь, PS/2-клава).

    Для мыши:
    > lsusb -t
    /: Bus 02.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/6p, 10000M
    /: Bus 01.Port 1: Dev 1, Class=root_hub, Driver=xhci_hcd/16p, 480M
    |__ Port 10: Dev 2, If 0, Class=Human Interface Device, Driver=usbhid, 12M
    |__ Port 10: Dev 2, If 1, Class=Human Interface Device, Driver=usbhid, 12M

    $ sudo su
    # echo disabled > /sys/bus/usb/devices/1-10/power/wakeup

    Клаву нашёл так:
    > cat /proc/acpi/wakeup
    ...
    PS2K S4 *enabled pnp:00:01
    ...
    # echo disabled > /sys/bus/pnp/devices/00:01/power/wakeup
    Ответ написан
    Комментировать