Последнее обновление: 16 November, 2022
Так получилось, что девушка, с которой мы познакомились и начали серьезные отношения, оказалась в горе кредитов. Совместно мы разработали жесткую систему финансового учета, с помощью которой мы закрыли все кредиты (более 100 000 гривен или в пересчете на текущий курс доллара – более 3500$).
Эта система помогла нам расправиться с кредитами в сравнительно короткие сроки: около 8 месяцев. Мой доход тогда еще был очень скромным – всего 500$ в месяц при том, что мы оба живем в столице.
Система довольно простая и выглядит вот так:
Периоды начинаются три раза в месяц: 5, 15 и 23 числа. В эти числа мы каждый раз скидываем одинаковые суммы в общий бюджет и на них и живем до начала следующего периода.
Так как моя девушка работает врачом и ей редко удается добраться до компьютера, то я сделал так, что мы можем заводить расходы через телеграм. Там у нас есть бот, который обрабатывает все наши сообщения, но в этом посте я не буду о нем много говорить. Подробнее о своем боте я уже писал.
Проблема была в том, что 5, 15 и 23 числа мне приходилось вручную "автопополнять" балансы всех нашей статей расходов и эта мелкая ручная работа раздражала. Статей расходов у нас несколько: на еду нам и коту, на бытовые штуки типа моющего, доставки, пакетов, на аренду и коммуналку, а раньше была и на кредиты. У всех них свои отдельные балансы и учет.
Каждое 5, 15 и 23 число месяца звучит, как классическая cron job. Теоретически можно было бы написать скрипт на питоне и запускать его по крону, поэтому то, как сделал я – это отнюдь не самое простое решение данной проблемы.
Я просто увидел, что у этих сервисов есть free tier, который вполне удовлетворяет моим потребностям, и мне захотелось поэкспериментировать с бессерверными функциями, которые сделал Google Cloud.
До этого я уже пользовался решением Amazon Lambda и потому мне было очень любопытно, как продвигаются дела с этим продуктом у основного конкурента Amazon.
Сервисы Google мне лично выглядят более удобными, чем у Amazon, но это я так думал еще до того, как попробовал их бессерверные функции.
Google Pub/Sub триггерится по крону и вкидывает в стрим сообщение (я так понял, это кафка, которую Google приспособил в качестве стриминга сообщений из одного своего продукта в другой). Google Cloud Function проект отрабатывает каждое сообщение из стрима: ловит, распаковывает и на основании данных внутри делает обновления в моей базе данных (я под это использую Notion, чтобы для моей девушки всегда был доступен удобный интерфейс и в вебе, и с мобильного приложения). После того, как необходимые обновления сделаны, функция отправляет уведомление на клиент о том сколько мы сэкономили в этом периоде и о том, что новый период открыт.
В интернете довольно мало работающих и актуальных примеров кода. Как именно зашифровано сообщение в кафке я так и не нашел, поэтому методом проб и ошибок удалось установить, как с этим работать.
Вот так выглядит entrypoint для моей Google Cloud Function.
def main_function(event, context):
"""Triggered from a message on a Cloud Pub/Sub topic.
Args:
event (dict): Event payload.
context (google.cloud.functions.Context): Metadata for the event.
"""
pubsub_message = base64.b64decode(event['data']).decode("utf-8")
pubsub_message = json.loads(pubsub_message)
day_triggered = pubsub_message.get("day")
print(f"day triggered is {day_triggered}")
if not day_triggered:
return
remain_categories_map = {}
for title in categories_to_update.keys():
res = notion.databases.query(**prepare_query_kwargs(title))
remain_value = get_remain_from_res(res)
remain_categories_map[title] = remain_value
message = "скинуть в банку нужно вот такие значения {}".format(
remain_categories_map
)
bot.send_message(chat_id=our_home_chat_id, text=message)
print("message sent")
for title, dates_dict in categories_to_update.items():
sum_for_open = dates_dict.get(day_triggered)
if sum_for_open:
print("data exist. Executing auto adding money.")
title = f"{title}_бот_открывает_период"
notion_page = notion_page_builder(
title,
dates_dict.get("id"),
0,
sum_for_open,
remain_flag=True,
bullets=None,
)
notion.pages.create(**notion_page)
bot.send_message(
chat_id=our_home_chat_id, text="Деньги пополнены, новый период открыт [с заботой о вас, ваш персональный робот]"
)
Для локального тестирования я нашел вот такой вот проект от Google.
Я использовал его для локального тестирования, но там не совсем актуальный способ шифрования сообщений в паб/саб. Когда я задеплоил функцию в облако, то оказалось, что паб/саб шифрует сообщение иначе.
Эта система работает уже 2 месяца и что я могу сказать – это был веселый эксперимент и все работает отлично.
Функционал ведет себя стабильно, не беспокоит его создателя (меня) и я сделал его абсолютно бесплатно. Надеюсь, что его стабильность не изменится и спустя какое-то время я вообще забуду, что он там есть.
Трой Кёлер - программист, живущий в Берлине, Германия. У него более 6 лет опыта работы в IT. Ранее он работал в одном из крупнейших интернет-магазинов Украины, а сейчас работает в Zalando. Он специализируется на языке программирования Rust, сложных бекенд системах, разработке продуктов и инженерных платформах.