diff --git a/poetry.lock b/poetry.lock index 875c38c..7b4cbb0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -760,7 +760,7 @@ python-versions = "*" [[package]] name = "sphinx" -version = "5.0.1" +version = "5.0.2" description = "Python documentation generator" category = "dev" optional = false @@ -791,18 +791,18 @@ test = ["pytest (>=4.6)", "html5lib", "cython", "typed-ast"] [[package]] name = "sphinx-autodoc-typehints" -version = "1.17.0" +version = "1.18.3" description = "Type hints (PEP 484) support for the Sphinx autodoc extension" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -Sphinx = ">=4" +Sphinx = ">=4.5" [package.extras] -testing = ["covdefaults (>=2)", "coverage (>=6)", "diff-cover (>=6.4)", "nptyping (>=1)", "pytest (>=6)", "pytest-cov (>=3)", "sphobjinv (>=2)", "typing-extensions (>=3.5)"] -type_comments = ["typed-ast (>=1.4.0)"] +testing = ["covdefaults (>=2.2)", "coverage (>=6.3)", "diff-cover (>=6.4)", "nptyping (>=2.1.2)", "pytest (>=7.1)", "pytest-cov (>=3)", "sphobjinv (>=2)", "typing-extensions (>=4.1)"] +type_comments = ["typed-ast (>=1.5.2)"] [[package]] name = "sphinxcontrib-applehelp" @@ -1021,7 +1021,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "3.10.4" -content-hash = "c372b6eaf5146204f5e9de78898858f1b0d644435778d3c7474120ad35a9ff5a" +content-hash = "b48912cc1b04f28ba8543f4527a380d2a462d733ab54a3920c7cd5a62970e976" [metadata.files] aiohttp = [ @@ -1812,12 +1812,12 @@ snowballstemmer = [ {file = "snowballstemmer-2.2.0.tar.gz", hash = "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1"}, ] sphinx = [ - {file = "Sphinx-5.0.1-py3-none-any.whl", hash = "sha256:36aa2a3c2f6d5230be94585bc5d74badd5f9ed8f3388b8eedc1726fe45b1ad30"}, - {file = "Sphinx-5.0.1.tar.gz", hash = "sha256:f4da1187785a5bc7312cc271b0e867a93946c319d106363e102936a3d9857306"}, + {file = "Sphinx-5.0.2-py3-none-any.whl", hash = "sha256:d3e57663eed1d7c5c50895d191fdeda0b54ded6f44d5621b50709466c338d1e8"}, + {file = "Sphinx-5.0.2.tar.gz", hash = "sha256:b18e978ea7565720f26019c702cd85c84376e948370f1cd43d60265010e1c7b0"}, ] sphinx-autodoc-typehints = [ - {file = "sphinx_autodoc_typehints-1.17.0-py3-none-any.whl", hash = "sha256:081daf53077b4ae1c28347d6d858e13e63aefe3b4aacef79fd717dd60687b470"}, - {file = "sphinx_autodoc_typehints-1.17.0.tar.gz", hash = "sha256:51c7b3f5cb9ccd15d0b52088c62df3094f1abd9612930340365c26def8629a14"}, + {file = "sphinx_autodoc_typehints-1.18.3-py3-none-any.whl", hash = "sha256:20294de2a818bda04953c5cb302ec5af46138c81980ad9efa6d8fc1fc4242518"}, + {file = "sphinx_autodoc_typehints-1.18.3.tar.gz", hash = "sha256:c04d8f8d70e988960e25b206af39a90df84e7e2c085bb24e123bc3684021b313"}, ] sphinxcontrib-applehelp = [ {file = "sphinxcontrib-applehelp-1.0.2.tar.gz", hash = "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58"}, diff --git a/pyproject.toml b/pyproject.toml index f085f25..c92ca1c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,8 +19,8 @@ psycopg2 = "2.9.3" aiohttp-devtools = "1.0.post0" pre-commit = "2.18.1" black = {version = "22.3.0",allow-prereleases = true} -sphinx-autodoc-typehints = "1.17.0" -sphinx = "5.0.1" +sphinx-autodoc-typehints = "1.18.3" +sphinx = "5.0.2" sphinxcontrib-trio = "1.1.2" lxml = "4.8.0" sphinxcontrib-programoutput = "0.17" diff --git a/src/os_credits/db_client/client.py b/src/os_credits/db_client/client.py index 4512b14..b26fc7d 100644 --- a/src/os_credits/db_client/client.py +++ b/src/os_credits/db_client/client.py @@ -10,7 +10,7 @@ from os_credits.settings import config from os_credits.db_client.model import Base, MetricCredits, Project, Credits, PromCatalogReflected, PromMetricReflected, \ make_measurement_class, Metric, Label, \ - BaseMeasurement + BaseMeasurement, LimitType from os_credits.log import timescaledb_logger @@ -258,6 +258,9 @@ async def get_granted_credits_for_project(self, project: Project, session): half_limit = project.granted_credits / 2.0 if project.used_credits < half_limit: project.half_limit_reached_send = False + if project.full_limit_reached_send: + if project.used_credits < project.granted_credits: + project.full_limit_reached_send = False await session.flush() else: timescaledb_logger.warning(f"Could not get granted credits for {project}") @@ -266,31 +269,37 @@ async def get_granted_credits_for_project(self, project: Project, session): except Exception as e: timescaledb_logger.exception(e) - async def inform_half_limit_reached(self, last_credits_entry, project, session): + async def inform_some_limit_reached(self, last_credits_entry, project, session, limit_type: LimitType): timeout = aiohttp.ClientTimeout(total=10, connect=5) data = { "project_name": project.project_name, "granted_credits": project.granted_credits, "used_credits": last_credits_entry.used_credits, - "timestamp": datetime.timestamp(last_credits_entry.time) + "timestamp": datetime.timestamp(last_credits_entry.time), + "limit_type": limit_type } headers = {"X-Api-Key": config["API_CONTACT_KEY"]} try: - timescaledb_logger.info(f"Sending information about half limit reached for {project} with {last_credits_entry}.") + timescaledb_logger.info(f"Sending information about {limit_type} for {project} with {last_credits_entry}.") async with self.client_session.post( - f"{config['MAIL_CONTACT_URL']}", + f"{config['MAIL_CONTACT_URL']}/credits-limit/", timeout=timeout, data=data, headers=headers ) as response: if response.status == 200: - project.half_limit_reached_send = True - await session.flush() - timescaledb_logger.info(f"Information about half limit reached send for {project} with {last_credits_entry}.") + if limit_type is LimitType.HALF_LIMIT_REACHED: + project.half_limit_reached_send = True + await session.flush() + timescaledb_logger.info(f"Information about {limit_type} send for {project} with {last_credits_entry}.") + elif limit_type is LimitType.FULL_LIMIT_REACHED: + project.full_limit_reached_send = True + await session.flush() + timescaledb_logger.info(f"Information about {limit_type} send for {project} with {last_credits_entry}.") else: - timescaledb_logger.warning(f"Could not send half limit reached mail for {project} with {last_credits_entry}") + timescaledb_logger.warning(f"Could not send {limit_type} mail for {project} with {last_credits_entry}") except ClientConnectorError: - timescaledb_logger.debug(f"No connection possible to send half limit reached mail for {project} with {last_credits_entry}.") + timescaledb_logger.debug(f"No connection possible to send {limit_type} mail for {project} with {last_credits_entry}.") except Exception as e: timescaledb_logger.exception(e) diff --git a/src/os_credits/db_client/model.py b/src/os_credits/db_client/model.py index 367a0cd..58af751 100644 --- a/src/os_credits/db_client/model.py +++ b/src/os_credits/db_client/model.py @@ -1,3 +1,5 @@ +from enum import Enum + from sqlalchemy import Column, String, Boolean, event, DDL, func, BigInteger, ForeignKey, Float, text from sqlalchemy.dialects.postgresql import TIMESTAMP from sqlalchemy.ext.declarative import DeferredReflection @@ -147,3 +149,8 @@ def _type(cls): return BaseMeasurement.__class__.__name__ return Measurement + + +class LimitType(str, Enum): + HALF_LIMIT_REACHED = "half limit reached" + FULL_LIMIT_REACHED = "full limit reached" diff --git a/src/os_credits/db_client/tasks.py b/src/os_credits/db_client/tasks.py index 7e24612..ab899e8 100644 --- a/src/os_credits/db_client/tasks.py +++ b/src/os_credits/db_client/tasks.py @@ -6,6 +6,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from os_credits.db_client.client import TimescaleDBManager +from os_credits.db_client.model import LimitType from os_credits.log import producer_logger, task_logger, TASK_ID from os_credits.settings import config @@ -172,7 +173,9 @@ async def compute_credits_by_label( credits_value=(last_credits_entry.used_credits + credits_value) ) if project.granted_credits > 0 and last_credits_entry.used_credits >= half_credits and not project.half_limit_reached_send: - await db_client.inform_half_limit_reached(last_credits_entry, project, session) + await db_client.inform_some_limit_reached(last_credits_entry, project, session, LimitType.HALF_LIMIT_REACHED) + if 0 < project.granted_credits <= last_credits_entry.used_credits and not project.full_limit_reached_send: + await db_client.inform_some_limit_reached(last_credits_entry, project, session, LimitType.FULL_LIMIT_REACHED) task_logger.debug("Last metric now: {0}".format(last_metric_credits)) task_logger.debug("Last credits now: {0}".format(last_credits_entry)) metric_num += 1 diff --git a/src/os_credits/settings.py b/src/os_credits/settings.py index 380035e..1c852ff 100644 --- a/src/os_credits/settings.py +++ b/src/os_credits/settings.py @@ -13,7 +13,6 @@ import json from collections import ChainMap from collections import UserDict -from decimal import Decimal from os import environ from typing import Any, TypedDict from typing import Dict