Skip to content

Commit

Permalink
Merge branch 'master' into detect-progress-regex-from-docker-label
Browse files Browse the repository at this point in the history
  • Loading branch information
bisgaard-itis authored Oct 2, 2023
2 parents fa409fb + 61faf41 commit 0a6afca
Show file tree
Hide file tree
Showing 44 changed files with 929 additions and 307 deletions.
57 changes: 40 additions & 17 deletions .env-devel
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ TRAEFIK_SIMCORE_ZONE=internal_simcore_stack

# NOTE: WEBSERVER_SESSION_SECRET_KEY = $(python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key())")

WEBSERVER_CREDIT_COMPUTATION_ENABLED=0

WEBSERVER_LOGLEVEL=INFO

WEBSERVER_PROJECTS={}
Expand Down Expand Up @@ -228,6 +230,8 @@ WEBSERVER_VERSION_CONTROL=1

AIODEBUG_SLOW_DURATION_SECS=0



# Webserver Garbage Collector

# the same in all deployments
Expand All @@ -236,59 +240,78 @@ WB_GC_LOGLEVEL=DEBUG
WB_GC_GARBAGE_COLLECTOR='{"GARBAGE_COLLECTOR_INTERVAL_S": 30}'
WB_GC_RESOURCE_MANAGER_RESOURCE_TTL_S=60

WB_GC_ANNOUNCEMENTS=0

#
# NOTE: PC->Yuri. The env-vars below are to "disable plugins" and therefore must not
# be changed. We could directly add them in the docker-compose environment section
# instead of having them also here. That will reduce the amount of env-vars to handle
#

WB_GC_ACTIVITY=null
WB_GC_ANNOUNCEMENTS=0
WB_GC_CATALOG=null
WB_GC_NOTIFICATIONS=0
WB_GC_CLUSTERS=0
WB_GC_DB_LISTENER=0
WB_GC_DIAGNOSTICS=null
WB_GC_EMAIL=null
WB_GC_EXPORTER=null
WB_GC_FRONTEND=null
WB_GC_LOGIN=null
WB_GC_PROJECTS=null
WB_GC_SCICRUNCH=null
WB_GC_STATICWEB=null

WB_GC_TRACING=null
WB_GC_CLUSTERS=0
WB_GC_GROUPS=0
WB_GC_INVITATIONS=null
WB_GC_LOGIN=null
WB_GC_META_MODELING=0
WB_GC_NOTIFICATIONS=0
WB_GC_PAYMENTS=null
WB_GC_PRODUCTS=0
WB_GC_PROJECTS=null
WB_GC_PUBLICATIONS=0
WB_GC_SCICRUNCH=null
WB_GC_SOCKETIO=1
WB_GC_STATICWEB=null
WB_GC_STUDIES_DISPATCHER=null
WB_GC_TAGS=0
WB_GC_TRACING=null
WB_GC_USERS=0
WB_GC_VERSION_CONTROL=0
WB_GC_WALLETS=0

# WebServer DB Event Listener

WB_DB_EL_LOGLEVEL=DEBUG
WB_DB_EL_DB_LISTENER=1
WB_DB_EL_SOCKETIO=1

WB_DB_EL_ANNOUNCEMENTS=0

#
# NOTE: PC->Yuri. The env-vars below are to "disable plugins" and therefore must not
# be changed. We could directly add them in the docker-compose environment section
# instead of having them also here. That will reduce the amount of env-vars to handle
#

WB_DB_EL_ACTIVITY=null
WB_DB_EL_ANNOUNCEMENTS=0
WB_DB_EL_CATALOG=null
WB_DB_EL_NOTIFICATIONS=0
WB_DB_EL_CLUSTERS=0
WB_DB_EL_DIAGNOSTICS=null
WB_DB_EL_EMAIL=null
WB_DB_EL_EXPORTER=null
WB_DB_EL_FRONTEND=null
WB_DB_EL_GARBAGE_COLLECTOR=null
WB_DB_EL_GROUPS=0
WB_DB_EL_INVITATIONS=null
WB_DB_EL_LOGIN=null
WB_DB_EL_META_MODELING=0
WB_DB_EL_NOTIFICATIONS=0
WB_DB_EL_PAYMENTS=null
WB_DB_EL_PRODUCTS=0
WB_DB_EL_PROJECTS=null
WB_DB_EL_PUBLICATIONS=0
WB_DB_EL_SCICRUNCH=null
WB_DB_EL_STATICWEB=null
WB_DB_EL_STORAGE=null
WB_DB_EL_STUDIES_DISPATCHER=null
WB_DB_EL_TRACING=null
WB_DB_EL_CLUSTERS=0
WB_DB_EL_GROUPS=0
WB_DB_EL_META_MODELING=0
WB_DB_EL_PRODUCTS=0
WB_DB_EL_PUBLICATIONS=0
WB_DB_EL_TAGS=0
WB_DB_EL_TRACING=null
WB_DB_EL_USERS=0
WB_DB_EL_VERSION_CONTROL=0
WB_DB_EL_WALLETS=0
5 changes: 4 additions & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
📝 Add or update documentation.
🔨 Add or update development scripts.
🔒️ Fix security issues.
⚠️ Changes in ops configuration etc. are required before deploying.
⚠️ Changes in ops configuration etc. are required before deploying.
[ Please add a link to the associated ops-issue or PR, such as in https://github.com/ITISFoundation/osparc-ops-environments or https://git.speag.com/oSparc/osparc-infra ]
🗃️ Database table changed (relevant for devops).
Expand All @@ -30,6 +30,9 @@ or from https://gitmoji.dev/
- resolves ITISFoundation/osparc-issues#428
- fixes #26
If openapi changes are provided, optionally point to the swagger editor with new changes
Example [openapi.json specs](https://editor.swagger.io/?url=https://raw.githubusercontent.com/<github-username>/osparc-simcore/is1133/create-api-for-creation-of-pricing-plan/services/web/server/src/simcore_service_webserver/api/v0/openapi.yaml)
-->


Expand Down
2 changes: 1 addition & 1 deletion api/specs/web-server/_products.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async def get_current_product_price():
...


@router.get(
@router.post(
"/invitation:generate",
response_model=Envelope[InvitationGenerated],
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ def upgrade():
"UPDATE payments_transactions SET state = 'PENDING' WHERE success IS NULL"
)
)
connection.execute("UPDATE payments_transactions SET state_message = errors")
connection.execute(
sa.DDL("UPDATE payments_transactions SET state_message = errors")
)

op.drop_column("payments_transactions", "success")
op.drop_column("payments_transactions", "errors")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import datetime
from dataclasses import dataclass
from decimal import Decimal
from typing import TypeAlias

import sqlalchemy as sa
from aiopg.sa.connection import SAConnection
from aiopg.sa.result import ResultProxy, RowProxy

from . import errors
from .models.payments_transactions import PaymentTransactionState, payments_transactions

PaymentID: TypeAlias = str

PaymentTransactionRow: TypeAlias = RowProxy


@dataclass
class PaymentFailure:
payment_id: str

def __bool__(self):
return False


class PaymentAlreadyExists(PaymentFailure):
...


class PaymentNotFound(PaymentFailure):
...


class PaymentAlreadyAcked(PaymentFailure):
...


async def insert_init_payment_transaction(
connection: SAConnection,
*,
payment_id: str,
price_dollars: Decimal,
osparc_credits: Decimal,
product_name: str,
user_id: int,
user_email: str,
wallet_id: int,
comment: str | None,
initiated_at: datetime.datetime,
) -> PaymentID | PaymentAlreadyExists:
"""Annotates 'init' transaction in the database"""
try:
await connection.execute(
payments_transactions.insert().values(
payment_id=payment_id,
price_dollars=price_dollars,
osparc_credits=osparc_credits,
product_name=product_name,
user_id=user_id,
user_email=user_email,
wallet_id=wallet_id,
comment=comment,
initiated_at=initiated_at,
)
)
except errors.UniqueViolation:
return PaymentAlreadyExists(payment_id)

return payment_id


async def update_payment_transaction_state(
connection: SAConnection,
*,
payment_id: str,
completion_state: PaymentTransactionState,
state_message: str | None = None,
) -> PaymentTransactionRow | PaymentNotFound | PaymentAlreadyAcked:
"""ACKs payment by updating state with SUCCESS, ..."""
if completion_state == PaymentTransactionState.PENDING:
msg = f"cannot update state with {completion_state=} since it is already initiated"
raise ValueError(msg)

optional = {}
if state_message:
optional["state_message"] = state_message

async with connection.begin():
row = await (
await connection.execute(
sa.select(
payments_transactions.c.initiated_at,
payments_transactions.c.completed_at,
)
.where(payments_transactions.c.payment_id == payment_id)
.with_for_update()
)
).fetchone()

if row is None:
return PaymentNotFound(payment_id=payment_id)

if row.completed_at is not None:
assert row.initiated_at < row.completed_at # nosec
return PaymentAlreadyAcked(payment_id=payment_id)

assert row.initiated_at # nosec

result = await connection.execute(
payments_transactions.update()
.values(completed_at=sa.func.now(), state=completion_state, **optional)
.where(payments_transactions.c.payment_id == payment_id)
.returning(sa.literal_column("*"))
)
row = await result.first()
assert row, "execute above should have caught this" # nosec

return row


async def get_user_payments_transactions(
connection: SAConnection,
*,
user_id: int,
offset: int | None = None,
limit: int | None = None,
) -> tuple[int, list[PaymentTransactionRow]]:
total_number_of_items = await connection.scalar(
sa.select(sa.func.count())
.select_from(payments_transactions)
.where(payments_transactions.c.user_id == user_id)
)
assert total_number_of_items is not None # nosec

# NOTE: what if between these two calls there are new rows? can we get this in an atomic call?å
stmt = (
payments_transactions.select()
.where(payments_transactions.c.user_id == user_id)
.order_by(payments_transactions.c.created.desc())
) # newest first

if offset is not None:
# psycopg2.errors.InvalidRowCountInResultOffsetClause: OFFSET must not be negative
stmt = stmt.offset(offset)

if limit is not None:
# InvalidRowCountInLimitClause: LIMIT must not be negative
stmt = stmt.limit(limit)

result: ResultProxy = await connection.execute(stmt)
rows = await result.fetchall() or []
return total_number_of_items, rows
Loading

0 comments on commit 0a6afca

Please sign in to comment.