Класс-декоратор Python: буфер событий и пакетная запись

Напишите решение на Python и проверьте его на странице.

Другие упражнения по этой теме: Классы-декораторы Python: задачи на call, методы и состояние.

Пакетный буфер событий

Модуль аудита собирает системные события и сохраняет их в удалённый журнал через функцию пакетной записи. Чтобы не открывать отдельную транзакцию на каждую мелкую запись, функцию оборачивают классом-декоратором с накопителем фиксированной вместимости.

При обычном вызове обёртка помещает очередное событие в буфер и возвращает его новую длину, не беспокоя саму функцию. Но как только накопитель заполняется до установленного предела, целевая функция немедленно вызывается со всем списком накопленных событий, буфер опустошается, а вызывающая сторона получает результат работы функции. Если же события больше не поступают, выгрузить остаток помогает метод flush(): при непустом буфере он отправляет накопленный список функции записи, очищает накопитель и возвращает полученный ответ, а при пустом буфере ничего не отправляет и возвращает None.

Если целевая функция завершается ошибкой, отправляемый пакет всё равно безвозвратно удаляется из буфера, а возникшее исключение беспрепятственно пробрасывается наружу. Напишите класс-декоратор, реализующий такую пакетную отправку и гарантированную очистку накопителя при сбое.

Что уже дано

В заготовке кода представлен класс BatchBuffer с заготовками методов __init__, __call__ и flush(), которые вам предстоит реализовать.

Что нужно сделать

Реализуйте класс BatchBuffer со следующей сигнатурой и поведением:

  • Конструктор __init__(self, function, capacity) принимает:
  • function — синхронный вызываемый объект, принимающий один аргумент (список событий). Функция может вернуть произвольный объект или возбудить исключение (включая производные от BaseException);
  • capacity — положительное целое число от 1 до 100, задающее предельную вместимость пакета.
  • Метод __call__(self, event) принимает произвольный объект события event (включая изменяемые объекты, подклассы и повторные ссылки):
  • добавляет событие в конец внутреннего накопителя, сохраняя исходный порядок, дубликаты и идентичность переданных объектов;
  • если после добавления число событий меньше capacity, целевая функция не вызывается, а метод возвращает новую длину очереди в виде целого числа int;
  • если же накопитель достиг ровно capacity событий, накопленный пакет немедленно передаётся в виде списка в function(batch). Метод возвращает результат выполнения целевой функции.
  • Метод flush(self) выгружает накопленный остаток:
  • если в накопителе есть хотя бы одно событие, оно передаётся в виде списка в function(batch) и возвращается результат выполнения функции;
  • если накопитель пуст, целевая функция не вызывается, а метод возвращает None.

Правила диспетчеризации и очистки:

  • При любой отправке пакета (как при заполнении до capacity, так и при flush()) отправляемые события должны быть безвозвратно удалены из накопителя независимо от того, завершилась ли целевая функция успешно или выбросила ошибку.
  • Если целевая функция выбрасывает исключение, то же самое исключение должно беспрепятственно всплыть наружу; повторные попытки отправки делать не нужно.
  • Состояние буфера должно быть изолировано для каждого созданного экземпляра: несколько независимых объектов BatchBuffer могут работать параллельно и чередовать вызовы.

Ввод и вывод

Стандартные потоки ввода stdin и вывода stdout в решении не используются: считывать ввод и вызывать print() не нужно. После выполнения кода учащегося проверяющая система считывает из пространства имён модуля класс верхнего уровня BatchBuffer и вызывает его методы с проверочными аргументами.

Пример использования

def write(events):
    return tuple(events)
buffer = BatchBuffer(write, 3)
print(buffer("a"))
print(buffer("b"))
print(buffer.flush())
print(buffer.flush())

Вывод:

1
2
('a', 'b')
None
РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Связанные задачи