Skip to content

Commit 2faf8ab

Browse files
authored
bugfix #1853: garbage collector deletes guest users (#1928)
* fixes bug #1853 * cleanup tests, warning, log and adds start banner in webserver
1 parent 3e03271 commit 2faf8ab

File tree

22 files changed

+327
-188
lines changed

22 files changed

+327
-188
lines changed

.gitignore

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,12 @@ prof/
153153
# outputs from make
154154
.stack-*.yml
155155

156-
157-
# Copies
156+
# copies
158157
services/**/.codeclimate.yml
158+
159159
# WSL
160160
.fake_hostname_file
161161
.bash_history
162+
163+
# pytest-fixture-tools output
164+
artifacts

packages/service-library/src/servicelib/logging_utils.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,13 @@ def set_logging_handler(
7575
formatting = DEFAULT_FORMATTING
7676
if not formatter_base:
7777
formatter_base = CustomFormatter
78-
for handler in logger.handlers:
7978

80-
# handler = logging.StreamHandler()
79+
for handler in logger.handlers:
8180
handler.setFormatter(
8281
formatter_base(
8382
"%(levelname)s: %(name)s:%(funcName)s(%(lineno)s) - %(message)s"
8483
)
8584
)
86-
# logger.addHandler(handler)
8785

8886

8987
def _log_arguments(
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,12 @@
1-
from .__version__ import __version__
1+
import warnings
2+
3+
from ._meta import __version__
4+
5+
#
6+
# NOTE: Some BaseSettings are using aliases (e.g. version for vtag) to facility construct
7+
# pydantic settings from names defined in trafaret schemas for the config files
8+
#
9+
warnings.filterwarnings(
10+
"ignore",
11+
message='aliases are no longer used by BaseSettings to define which environment variables to read. Instead use the "env" field setting. See https://pydantic-docs.helpmanual.io/usage/settings/#environment-variable-names',
12+
)

services/web/server/src/simcore_service_webserver/__version__.py renamed to services/web/server/src/simcore_service_webserver/_meta.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,15 @@
1414

1515
# legacy
1616
api_version_prefix: str = api_vtag
17+
18+
19+
WELCOME_MSG = r"""
20+
_ _ _
21+
| | | | | |
22+
| | | | ___ | |__ ___ ___ _ __ __ __ ___ _ __
23+
| |/\| | / _ \| '_ \ / __| / _ \| '__|\ \ / // _ \| '__|
24+
\ /\ /| __/| |_) |\__ \| __/| | \ V /| __/| |
25+
\/ \/ \___||_.__/ |___/ \___||_| \_/ \___||_| {0}
26+
""".format(
27+
f"v{__version__}"
28+
)

services/web/server/src/simcore_service_webserver/application.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from servicelib.application import create_safe_application
1111

12+
from ._meta import WELCOME_MSG
1213
from .activity import setup_activity
1314
from .catalog import setup_catalog
1415
from .computation import setup_computation
@@ -67,14 +68,14 @@ def create_application(config: Dict) -> web.Application:
6768
setup_storage(app)
6869
setup_users(app)
6970
setup_groups(app)
70-
setup_projects(app) # needs storage
71-
setup_studies_access(app)
71+
setup_projects(app)
7272
setup_activity(app)
7373
setup_resource_manager(app)
7474
setup_tags(app)
7575
setup_catalog(app)
7676
setup_publications(app)
7777
setup_products(app)
78+
setup_studies_access(app)
7879

7980
return app
8081

@@ -85,6 +86,11 @@ def run_service(config: dict):
8586

8687
app = create_application(config)
8788

89+
async def welcome_banner(_app: web.Application):
90+
print(WELCOME_MSG, flush=True)
91+
92+
app.on_startup.append(welcome_banner)
93+
8894
web.run_app(app, host=config["main"]["host"], port=config["main"]["port"])
8995

9096

services/web/server/src/simcore_service_webserver/catalog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from servicelib.rest_responses import wrap_as_envelope
1414
from servicelib.rest_routing import iter_path_operations
1515

16-
from .__version__ import api_version_prefix
16+
from ._meta import api_version_prefix
1717
from .catalog_config import assert_valid_config, get_client_session
1818
from .constants import RQ_PRODUCT_KEY, X_PRODUCT_NAME_HEADER
1919
from .login.decorators import RQT_USERID_KEY, login_required

services/web/server/src/simcore_service_webserver/cli.py

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,12 @@
1818
from argparse import ArgumentParser
1919
from typing import Dict, List, Optional
2020

21-
from aiodebug import log_slow_callbacks
22-
from aiohttp.log import access_logger
23-
from servicelib.logging_utils import set_logging_handler
24-
2521
from .application import run_service
2622
from .application_config import CLI_DEFAULT_CONFIGFILE, app_schema
2723
from .cli_config import add_cli_options, config_from_options
24+
from .log import setup_logging
2825
from .utils import search_osparc_repo_dir
2926

30-
LOG_LEVEL_STEP = logging.CRITICAL - logging.ERROR
31-
3227
log = logging.getLogger(__name__)
3328

3429

@@ -104,26 +99,7 @@ def main(args: Optional[List] = None):
10499
config = parse(args, parser)
105100

106101
# service log level
107-
log_level = getattr(logging, config["main"]["log_level"])
108-
logging.basicConfig(level=log_level)
109-
logging.root.setLevel(log_level)
110-
set_logging_handler(logging.root)
111-
112-
# aiohttp access log-levels
113-
access_logger.setLevel(log_level)
114-
115-
# keep mostly quiet noisy loggers
116-
quiet_level = max(
117-
min(log_level + LOG_LEVEL_STEP, logging.CRITICAL), logging.WARNING
118-
)
119-
logging.getLogger("engineio").setLevel(quiet_level)
120-
logging.getLogger("openapi_spec_validator").setLevel(quiet_level)
121-
logging.getLogger("sqlalchemy").setLevel(quiet_level)
122-
logging.getLogger("sqlalchemy.engine").setLevel(quiet_level)
123-
124-
# NOTE: Every task blocking > AIODEBUG_SLOW_DURATION_SECS secs is considered slow and logged as warning
125-
slow_duration = float(os.environ.get("AIODEBUG_SLOW_DURATION_SECS", 0.1))
126-
log_slow_callbacks.enable(slow_duration)
102+
setup_logging(level=config["main"]["log_level"])
127103

128104
# run
129105
run_service(config)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
""" Configuration and utilities for service logging
2+
3+
"""
4+
import logging
5+
import os
6+
from typing import Union
7+
8+
from aiodebug import log_slow_callbacks
9+
from aiohttp.log import access_logger
10+
11+
from servicelib.logging_utils import set_logging_handler
12+
13+
LOG_LEVEL_STEP = logging.CRITICAL - logging.ERROR
14+
15+
16+
def setup_logging(*, level: Union[str, int]):
17+
# service log level
18+
logging.basicConfig(level=level)
19+
20+
# root
21+
logging.root.setLevel(level)
22+
set_logging_handler(logging.root)
23+
24+
# aiohttp access log-levels
25+
access_logger.setLevel(level)
26+
27+
# keep mostly quiet noisy loggers
28+
quiet_level: int = max(min(logging.root.level + LOG_LEVEL_STEP, logging.CRITICAL), logging.WARNING)
29+
logging.getLogger("engineio").setLevel(quiet_level)
30+
logging.getLogger("openapi_spec_validator").setLevel(quiet_level)
31+
logging.getLogger("sqlalchemy").setLevel(quiet_level)
32+
logging.getLogger("sqlalchemy.engine").setLevel(quiet_level)
33+
34+
# NOTE: Every task blocking > AIODEBUG_SLOW_DURATION_SECS secs is considered slow and logged as warning
35+
slow_duration = float(os.environ.get("AIODEBUG_SLOW_DURATION_SECS", 0.1))
36+
log_slow_callbacks.enable(slow_duration)
37+
38+
39+
def test_logger_propagation(logger: logging.Logger):
40+
msg = f"TESTING %s log with {logger}"
41+
logger.critical(msg, "critical")
42+
logger.error(msg, "error")
43+
logger.info(msg, "info")
44+
logger.warning(msg, "warning")
45+
logger.debug(msg, "debug")

services/web/server/src/simcore_service_webserver/products.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from pydantic import BaseModel, ValidationError, validator
88
from servicelib.application_setup import ModuleCategory, app_module_setup
99

10-
from .__version__ import api_vtag
10+
from ._meta import api_vtag
1111
from .constants import (
1212
APP_DB_ENGINE_KEY,
1313
APP_PRODUCTS_KEY,

services/web/server/src/simcore_service_webserver/resource_manager/config.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import trafaret as T
99
from aiohttp.web import Application
10-
from pydantic import BaseSettings, PositiveInt
10+
from pydantic import BaseSettings, PositiveInt, Field
1111

1212
from models_library.settings.redis import RedisConfig
1313
from servicelib.application_keys import APP_CONFIG_KEY
@@ -46,8 +46,12 @@ class RedisSection(RedisConfig):
4646
class ResourceManagerSettings(BaseSettings):
4747
enabled: bool = True
4848

49-
resource_deletion_timeout_seconds: Optional[PositiveInt] = 900
50-
garbage_collection_interval_seconds: Optional[PositiveInt] = 30
49+
resource_deletion_timeout_seconds: Optional[PositiveInt] = Field(
50+
900, description="Expiration time (or Time to live (TTL) in redis jargon) for a registered resource"
51+
)
52+
garbage_collection_interval_seconds: Optional[PositiveInt] = Field(
53+
30, description="Waiting time between consecutive runs of the garbage-colector"
54+
)
5155

5256
redis: RedisSection
5357

0 commit comments

Comments
 (0)