diff options
Diffstat (limited to 'jb/flow')
| -rw-r--r-- | jb/flow/assignment_tasks.py | 468 | ||||
| -rw-r--r-- | jb/flow/events.py | 94 | ||||
| -rw-r--r-- | jb/flow/maintenance.py | 4 | ||||
| -rw-r--r-- | jb/flow/monitoring.py | 23 | ||||
| -rw-r--r-- | jb/flow/setup_tasks.py | 5 | ||||
| -rw-r--r-- | jb/flow/tasks.py | 23 |
6 files changed, 60 insertions, 557 deletions
diff --git a/jb/flow/assignment_tasks.py b/jb/flow/assignment_tasks.py index 18a844e..b3c820a 100644 --- a/jb/flow/assignment_tasks.py +++ b/jb/flow/assignment_tasks.py @@ -1,37 +1,15 @@ -import logging -import math -from datetime import timedelta -from typing import Optional - -from generalresearchutils.models.thl.definitions import PayoutStatus, StatusCode1 -from generalresearchutils.models.thl.wallet.cashout_method import CashoutRequestInfo -from generalresearchutils.currency import USDCent - -from jb.flow.monitoring import emit_error_event, emit_assignment_event, emit_bonus_event +from jb.decorators import LOG +from jb.flow.monitoring import emit_assignment_event, emit_error_event from jb.managers.amt import ( - AMTManager, REJECT_MESSAGE_UNKNOWN_ASSIGNMENT, - REJECT_MESSAGE_NO_WORK, - NO_WORK_APPROVAL_MESSAGE, - REJECT_MESSAGE_BADDIE, - APPROVAL_MESSAGE, - BONUS_MESSAGE, -) -from jb.managers.thl import ( - get_user_blocked, - get_task_status, - user_cashout_request, - manage_pending_cashout, - get_user_blocked_or_not_exists, - get_wallet_balance_if_non_negative, + AMTManager, ) +from jb.managers.assignment import AssignmentManager +from jb.managers.bonus import BonusManager +from jb.managers.hit import HitManager from jb.models.assignment import Assignment from jb.models.definitions import AssignmentStatus from jb.models.event import MTurkEvent -from jb.managers.assignment import AssignmentManager -from jb.managers.hit import HitManager -from jb.managers.bonus import BonusManager -from jb.config import settings def process_assignment_submitted( @@ -42,16 +20,13 @@ def process_assignment_submitted( event: MTurkEvent, ) -> None: """ - Called either directly or from the SNS Notification that a - HIT was submitted - - :return: None + Reject any submitted assignments """ # # Step 1: Attempt to get the Assignment out of the API # - logging.info(f"{event=}") + LOG.info(f"{event=}") # This is the assignment model from AMT. In the DB, we should only have # the AssignmentStub @@ -66,95 +41,26 @@ def process_assignment_submitted( # It is not found in amt, either it is invalid, not yet submitted, or # already been approved/rejected, so we just do nothing ... # todo: maybe we confirm its state matches what we have in the db - logging.warning(f"No assignment found on AMT: {event.amt_assignment_id}") + LOG.warning(f"No assignment found on AMT: {event.amt_assignment_id}") emit_error_event( event_type="assignment_not_found_in_amt", amt_hit_type_id=event.amt_hit_type_id, ) - return None + return # Even if the assignment doesn't exist, the hit must ... hit = hm.get_from_amt_id(amt_hit_id=assignment.amt_hit_id) - # - # Step 2: Attempt to get the Assignment out of the DB - # - # Now, we need to confirm it is something that we have in the db. If not, - # that means either something broke, or some funny business is happening - # (maybe a baddie is submitting an assignment without doing any work). - stub = am.get_stub_if_exists(amt_assignment_id=assignment.amt_assignment_id) - if stub is None: - # When they visited the "work" page, it should have created an - # AssignmentStub in the db. If that doesn't exist, something bad - # happened. - logging.warning(f"No assignment found in DB: {event.amt_assignment_id}") - emit_error_event( - event_type="assignment_stub_not_found_in_db", - amt_hit_type_id=event.amt_hit_type_id, - ) - reject_assignment( - amtm=amtm, - am=am, - hm=hm, - amt_assignment_id=assignment.amt_assignment_id, - msg=REJECT_MESSAGE_UNKNOWN_ASSIGNMENT, - amt_hit_type_id=hit.amt_hit_type_id, - ) - review_hit(amtm=amtm, hm=hm, assignment=assignment) - return None - - assert assignment.amt_assignment_id == event.amt_assignment_id - assert assignment.amt_hit_id == event.amt_hit_id - assert assignment.amt_hit_id == stub.amt_hit_id - assert assignment.amt_worker_id == stub.amt_worker_id - amt_assignment_id = assignment.amt_assignment_id - amt_worker_id = assignment.amt_worker_id - - # We don't have a TSID associated with the assignment until we the - # assignment is submitted. - am.update_answer(assignment=assignment) - - # check if the user is blocked by thl - if get_user_blocked_or_not_exists(amt_worker_id=amt_worker_id): - logging.warning( - f"User {amt_worker_id} blocked or not exists. Rejecting: {amt_assignment_id}" - ) - emit_error_event( - event_type="assignment_submitted_user_blocked_or_not_exists", - amt_hit_type_id=event.amt_hit_type_id, - ) - reject_assignment( - amtm=amtm, - am=am, - hm=hm, - amt_assignment_id=amt_assignment_id, - msg=REJECT_MESSAGE_BADDIE, - amt_hit_type_id=hit.amt_hit_type_id, - ) - review_hit(amtm=amtm, hm=hm, assignment=assignment) - return None - - if assignment.tsid is None: - assignment = handle_assignment_w_no_work( - amtm=amtm, am=am, hm=hm, assignment=assignment - ) - else: - # We need to validate the work exists on thl, and if so, approve - assignment = handle_assignment_w_work( - amtm=amtm, am=am, hm=hm, assignment=assignment - ) - - # - # Step 4: Tell Amazon we've reviewed the HIT, and update the DB - # + reject_assignment( + amtm=amtm, + am=am, + hm=hm, + amt_assignment_id=assignment.amt_assignment_id, + msg=REJECT_MESSAGE_UNKNOWN_ASSIGNMENT, + amt_hit_type_id=hit.amt_hit_type_id, + ) review_hit(amtm=amtm, hm=hm, assignment=assignment) - - if ( - assignment.tsid - and assignment.status == AssignmentStatus.Approved - and assignment.requester_feedback != NO_WORK_APPROVAL_MESSAGE - ): - return issue_worker_payment(amtm=amtm, hm=hm, bm=bm, assignment=assignment) + return def review_hit(amtm: AMTManager, hm: HitManager, assignment: Assignment) -> None: @@ -163,66 +69,13 @@ def review_hit(amtm: AMTManager, hm: HitManager, assignment: Assignment) -> None hit, _ = amtm.get_hit_if_exists(amt_hit_id=assignment.amt_hit_id) if hit is None: - logging.warning( - f"Hit not found when trying to review hit: {assignment.amt_hit_id}" - ) - return None + LOG.warning(f"Hit not found when trying to review hit: {assignment.amt_hit_id}") + return # Update the db hm.update_hit(hit) - return None - - -def handle_assignment_w_no_work( - amtm: AMTManager, am: AssignmentManager, hm: HitManager, assignment: Assignment -) -> Assignment: - """ - Called when an assignment is submitted without a wall event. - Not entirely clear why this happens. I think they accept a HIT, get no work - available for whatever reason, then report, and submit it. - - :return: The Assignment - """ - logging.warning( - f"Assignment submitted with no tsid: {assignment.amt_assignment_id}" - ) - amt_worker_id = assignment.amt_worker_id - amt_assignment_id = assignment.amt_assignment_id - hit = hm.get_from_amt_id(amt_hit_id=assignment.amt_hit_id) - emit_error_event( - event_type="assignment_submitted_no_work", - amt_hit_type_id=hit.amt_hit_type_id, - ) - - # They get 0 chances due to abuse - if True: - # if (am.missing_tsid_count(amt_worker_id=amt_worker_id) >= 3) or ( - # am.rejected_count(amt_worker_id=amt_worker_id) >= 3 - # or get_user_blocked(amt_worker_id=amt_worker_id) - # ): - assignment = reject_assignment( - amtm=amtm, - am=am, - hm=hm, - amt_assignment_id=amt_assignment_id, - msg=REJECT_MESSAGE_NO_WORK, - amt_hit_type_id=hit.amt_hit_type_id, - ) - # todo: we don't have a way to "block" a user (i.e. tattle to thl) - # make_block_worker_decision(user) - return assignment - - # Approve with a message explaining they shouldn't do it. - assignment = approve_assignment( - amtm=amtm, - am=am, - amt_assignment_id=amt_assignment_id, - msg=NO_WORK_APPROVAL_MESSAGE, - amt_hit_type_id=hit.amt_hit_type_id, - ) - - return assignment + return def reject_assignment( @@ -245,7 +98,7 @@ def reject_assignment( event_type="failed_to_reject_assignment", amt_hit_type_id=amt_hit_type_id, ) - logging.exception(f"Failed to reject assignment: {amt_assignment_id}") + LOG.exception(f"Failed to reject assignment: {amt_assignment_id}") # We just rejected this assignment, get it from amazon again assignment = amtm.get_assignment(amt_assignment_id=amt_assignment_id) @@ -256,7 +109,7 @@ def reject_assignment( # need to create as assignment first ... stub = am.get_stub_if_exists(amt_assignment_id=assignment.amt_assignment_id) if stub is None: - logging.warning( + LOG.warning( f"Rejected assignment doesn't exist in DB. Creating ... : {amt_assignment_id}" ) # Even if the assignment doesn't exist, the hit must ... @@ -267,276 +120,5 @@ def reject_assignment( emit_assignment_event( status=AssignmentStatus.Rejected, amt_hit_type_id=amt_hit_type_id, reason=msg ) - logging.warning(f"Rejected assignment: {amt_assignment_id}") + LOG.warning(f"Rejected assignment: {amt_assignment_id}") return assignment - - -def approve_assignment( - amtm: AMTManager, - am: AssignmentManager, - amt_assignment_id: str, - msg: str, - amt_hit_type_id: str, - override_rejection: bool = False, -) -> Assignment: - # Approve in AMT, update db - - res = amtm.approve_assignment_if_possible( - amt_assignment_id=amt_assignment_id, - msg=msg, - override_rejection=override_rejection, - ) - if res is None: - # We failed to approve this assignment. Cannot distinguish between - # failed b/c assignment is already approved, or it is not possible. - emit_error_event( - event_type="failed_to_approve_assignment", - amt_hit_type_id=amt_hit_type_id, - ) - # The assignment might already be approved, the error msg is useless, so - # keep going. - # raise Exception(f"Failed to approve assignment: {amt_assignment_id}") - - # We just approved this assignment, get it from amazon again - assignment = amtm.get_assignment(amt_assignment_id=amt_assignment_id) - assert assignment.status == AssignmentStatus.Approved - # And update the db - am.approve(assignment=assignment) - emit_assignment_event( - status=AssignmentStatus.Approved, amt_hit_type_id=amt_hit_type_id, reason=msg - ) - logging.warning(f"Approved assignment: {amt_assignment_id}") - return assignment - - -def handle_assignment_w_work( - amtm: AMTManager, am: AssignmentManager, hm: HitManager, assignment: Assignment -) -> Assignment: - """ - Called when an assignment is submitted with a tsid. - - Check the tsid (thl status endpoint). Make sure it is finished, and - stuff matches (doesn't matter if not a complete) - - Try to submit a cashout request for the HIT payout (e.g. 5c) - """ - - amt_worker_id = assignment.amt_worker_id - amt_assignment_id = assignment.amt_assignment_id - tsid = assignment.tsid - assert ( - tsid is not None - ), "Assignment must have a tsid to be handled in handle_assignment_w_work" - - hit = hm.get_from_amt_id(amt_hit_id=assignment.amt_hit_id) - - tsr = get_task_status(tsid=tsid) - if ( - tsr is None - or tsr.status is None - or tsr.status_code_1 - in { - StatusCode1.SESSION_START_FAIL, - StatusCode1.SESSION_START_QUALITY_FAIL, - StatusCode1.SESSION_CONTINUE_QUALITY_FAIL, - } - ): - # TSID doesn't exist or work is not finished: - # Reject the assignment instead - if tsr is not None and tsr.status_code_1 in { - StatusCode1.SESSION_START_QUALITY_FAIL, - StatusCode1.SESSION_CONTINUE_QUALITY_FAIL, - }: - event_type = "assignment_submitted_quality_fail" - else: - event_type = "assignment_submitted_work_not_complete" - - emit_error_event( - event_type=event_type, - amt_hit_type_id=hit.amt_hit_type_id, - ) - assignment = reject_assignment( - amtm=amtm, - am=am, - hm=hm, - amt_assignment_id=amt_assignment_id, - msg=REJECT_MESSAGE_BADDIE, - amt_hit_type_id=hit.amt_hit_type_id, - ) - return assignment - - assert tsr.product_user_id == amt_worker_id - assert tsr.finished is not None - assert (tsr.finished - assignment.created_at) <= timedelta(minutes=90) - - # Request an AMT_ASSIGNMENT cashout for 1c - req = submit_and_approve_amt_assignment_request( - amt_worker_id=amt_worker_id, amount=hit.reward - ) - if req is None: - # Reject the assignment instead - logging.warning( - f"submit_and_approve_amt_assignment_request failed: {amt_assignment_id}" - ) - emit_error_event( - event_type="assignment_cashout_request_failed", - amt_hit_type_id=hit.amt_hit_type_id, - ) - assignment = reject_assignment( - amtm=amtm, - am=am, - hm=hm, - amt_assignment_id=amt_assignment_id, - msg=REJECT_MESSAGE_BADDIE, - amt_hit_type_id=hit.amt_hit_type_id, - ) - return assignment - - assert req.id - - # We've approved the HIT payment, now update the db to reflect this, and approve the assignment - assignment = approve_assignment( - amtm=amtm, - am=am, - amt_assignment_id=amt_assignment_id, - msg=APPROVAL_MESSAGE, - amt_hit_type_id=hit.amt_hit_type_id, - ) - # We complete after the assignment is approved - complete_res = manage_pending_cashout( - cashout_id=req.id, payout_status=PayoutStatus.COMPLETE - ) - if complete_res.status != PayoutStatus.COMPLETE: - # unclear wny this would happen - raise ValueError(f"Failed to complete cashout: {req.id}") - return assignment - - -def submit_and_approve_amt_assignment_request( - amt_worker_id: str, amount: USDCent -) -> Optional[CashoutRequestInfo]: - # If successful, returns the cashout id, otherwise, returns None - req = user_cashout_request( - amt_worker_id=amt_worker_id, - amount=amount, - cashout_method_id=settings.amt_assignment_cashout_method, - ) - assert req.id - - if req.status != PayoutStatus.PENDING: - return None - - approve_res = manage_pending_cashout(req.id, PayoutStatus.APPROVED) - if approve_res.status != PayoutStatus.APPROVED: - return None - - return req - - -def submit_and_approve_amt_bonus_request( - amt_worker_id: str, amount: USDCent -) -> Optional[CashoutRequestInfo]: - # If successful, returns the cashout id, otherwise, returns None - req = user_cashout_request( - amt_worker_id=amt_worker_id, - amount=amount, - cashout_method_id=settings.amt_bonus_cashout_method, - ) - assert req.id - - if req.status != PayoutStatus.PENDING: - return None - - approve_res = manage_pending_cashout(req.id, PayoutStatus.APPROVED) - if approve_res.status != PayoutStatus.APPROVED: - return None - - return req - - -def issue_worker_payment( - amtm: AMTManager, hm: HitManager, bm: BonusManager, assignment: Assignment -) -> None: - # For now, since we have no "I want my bonus" request/button. A user's - # balance will be sent out anytime they get an approved assignment. We - # don't need the task status, the tsid, nor the amount / user_payout - # that was paid, or anything. - # We just get the wallet balance and submit a cashout request if >0 - # then approve it, send the amt bonus, then complete it - amt_assignment_id = assignment.amt_assignment_id - hit = hm.get_from_amt_id(amt_hit_id=assignment.amt_hit_id) - wallet_balance = get_wallet_balance_if_non_negative( - amt_worker_id=assignment.amt_worker_id - ) - if not wallet_balance: - return None - amount = round_payment(amount=wallet_balance) - if not amount: - return None - - # Don't send more than $4.97 at a time. If they have a higher wallet balance, - # they just need to get another hit approved. - amount = min(amount, USDCent(4_97)) - - pe = submit_and_approve_amt_bonus_request( - amt_worker_id=assignment.amt_worker_id, amount=amount - ) - if pe is None: - logging.warning( - f"submit_and_approve_amt_bonus_request failed: {amt_assignment_id}" - ) - emit_error_event( - event_type="bonus_cashout_request_failed", - amt_hit_type_id=hit.amt_hit_type_id, - ) - return None - assert pe.id - - amtm.send_bonus( - amt_worker_id=assignment.amt_worker_id, - amt_assignment_id=assignment.amt_assignment_id, - amount=amount, - reason=BONUS_MESSAGE, - unique_request_token=pe.id, - ) - - # Confirm it was sent through amt - bonus = amtm.get_bonus( - amt_assignment_id=assignment.amt_assignment_id, payout_event_id=pe.id - ) - - if bonus is None: - logging.warning( - f"Failed to find bonus after sending it: {amt_assignment_id} {pe.id}" - ) - emit_error_event( - event_type="bonus_not_found_after_sending", - amt_hit_type_id=hit.amt_hit_type_id, - ) - return None - - # Create in DB - bm.create(bonus=bonus) - emit_bonus_event(amount=amount, amt_hit_type_id=hit.amt_hit_type_id) - - # Complete cashout - res = manage_pending_cashout(pe.id, PayoutStatus.COMPLETE) - if res.status != PayoutStatus.COMPLETE: - raise ValueError( - f"{assignment.amt_assignment_id} {pe.id=} manage_pending_cashout COMPLETE failed: {res=}" - ) - - -def round_payment(amount: USDCent) -> USDCent: - """ - Don't pay bonuses less than 7 cents, just add it to their wallet. - Round down bonuses (>=7 cents) to the nearest multiple of 5 - starting at 2 - """ - if amount < 7: - return USDCent(0) - - amt = (5 * math.floor((int(amount) - 2) / 5)) + 2 - - payout = USDCent(amt) - assert 0 <= payout <= 40_00, "Payout must be between $0.00 and $40.00" - - return payout diff --git a/jb/flow/events.py b/jb/flow/events.py index 2825cb1..bee63fd 100644 --- a/jb/flow/events.py +++ b/jb/flow/events.py @@ -1,18 +1,16 @@ -import logging import time from concurrent import futures -from concurrent.futures import ThreadPoolExecutor, Executor -from typing import Optional, cast, TypedDict +from concurrent.futures import Executor, ThreadPoolExecutor +from typing import cast import redis from jb.config import ( - JB_EVENTS_STREAM, CONSUMER_GROUP, CONSUMER_NAME, - JB_EVENTS_FAILED_STREAM, + JB_EVENTS_STREAM, ) -from jb.decorators import REDIS +from jb.decorators import LOG, get_redis from jb.flow.assignment_tasks import process_assignment_submitted from jb.flow.monitoring import emit_error_event from jb.models.event import MTurkEvent @@ -20,13 +18,6 @@ from jb.models.event import MTurkEvent StreamMessages = list[tuple[str, list[tuple[bytes, dict[bytes, bytes]]]]] -class PendingEntry(TypedDict): - message_id: bytes - consumer: bytes - time_since_delivered: int - times_delivered: int - - def process_mturk_events_task(): executor = ThreadPoolExecutor(max_workers=5) create_consumer_group() @@ -34,21 +25,11 @@ def process_mturk_events_task(): try: process_mturk_events(executor=executor) except Exception as e: - logging.exception(e) + LOG.exception(e) finally: time.sleep(1) -def handle_pending_msgs_task(): - while True: - try: - handle_pending_msgs() - except Exception as e: - logging.exception(e) - finally: - time.sleep(60) - - def process_mturk_events(executor: Executor): while True: n = process_mturk_events_chunk(executor=executor) @@ -58,7 +39,10 @@ def process_mturk_events(executor: Executor): def create_consumer_group(): try: - REDIS.xgroup_create(JB_EVENTS_STREAM, CONSUMER_GROUP, id="0", mkstream=True) + redis_client = get_redis() + redis_client.xgroup_create( + JB_EVENTS_STREAM, CONSUMER_GROUP, id="0", mkstream=True + ) except redis.exceptions.ResponseError as e: if "BUSYGROUP Consumer Group name already exists" in str(e): pass # group already exists @@ -66,8 +50,9 @@ def create_consumer_group(): raise -def process_mturk_events_chunk(executor: Executor) -> Optional[int]: - msgs_raw = REDIS.xreadgroup( +def process_mturk_events_chunk(executor: Executor) -> int | None: + redis_client = get_redis() + msgs_raw = redis_client.xreadgroup( groupname=CONSUMER_GROUP, consumername=CONSUMER_NAME, streams={JB_EVENTS_STREAM: ">"}, @@ -89,66 +74,25 @@ def process_mturk_events_chunk(executor: Executor) -> Optional[int]: executor.submit(process_assignment_submitted_event, event, str(msg_id)) ) else: - logging.info(f"Discarding {event}") - REDIS.xdel(JB_EVENTS_STREAM, msg_id) + LOG.info(f"Discarding {event}") + redis_client.xdel(JB_EVENTS_STREAM, msg_id) futures.wait(fs, timeout=60) return len(msgs) def process_assignment_submitted_event(event: MTurkEvent, msg_id: str): - from jb.decorators import AMTM, AM, HM, BM + from jb.decorators import AM, AMTM, BM, HM + + redis_client = get_redis() try: process_assignment_submitted(amtm=AMTM, am=AM, hm=HM, bm=BM, event=event) except Exception as e: - logging.exception(f"{event.amt_assignment_id=}, {e=}") + LOG.exception(f"{event.amt_assignment_id=}, {e=}") emit_error_event( event_type="failed_process_assignment_submitted", amt_hit_type_id=event.amt_hit_type_id, ) - REDIS.xackdel(JB_EVENTS_STREAM, CONSUMER_GROUP, msg_id) - - -def handle_pending_msgs(): - # TODO!: This doesn't run at all. - - # Looks in the redis queue for msgs that - # are pending (read by a consumer but not ACK). These prob failed. - # Below is from chatgpt, idk if it works - pending = cast( - list[PendingEntry], - REDIS.xpending_range( - JB_EVENTS_STREAM, CONSUMER_GROUP, min="-", max="+", count=10 - ), - ) - - for entry in pending: - msg_id = entry["message_id"] - # Claim message if idle > 10 sec - if entry["idle"] > 10_000: # milliseconds - claimed = REDIS.xclaim( - JB_EVENTS_STREAM, - CONSUMER_GROUP, - CONSUMER_NAME, - min_idle_time=10_000, - message_ids=[msg_id], - ) - for cid, data in claimed: - msg_json = data["data"] - event = MTurkEvent.model_validate_json(msg_json) - if event.event_type == "AssignmentSubmitted": - # Try to process it again. If it fails, add - # it to the failed stream, so maybe we can fix - # and try again? - try: - process_assignment_submitted_event(event, cid) - REDIS.xack(JB_EVENTS_STREAM, CONSUMER_GROUP, cid) - except Exception as e: - logging.exception(e) - REDIS.xadd(JB_EVENTS_FAILED_STREAM, data) - REDIS.xack(JB_EVENTS_STREAM, CONSUMER_GROUP, cid) - else: - logging.info(f"Discarding {event}") - REDIS.xdel(JB_EVENTS_STREAM, msg_id) + redis_client.xackdel(JB_EVENTS_STREAM, CONSUMER_GROUP, msg_id) diff --git a/jb/flow/maintenance.py b/jb/flow/maintenance.py index f8ca971..4a2fe81 100644 --- a/jb/flow/maintenance.py +++ b/jb/flow/maintenance.py @@ -1,5 +1,3 @@ -from typing import Optional - from jb.decorators import HM from jb.flow.monitoring import emit_hit_event from jb.managers.amt import AMTManager @@ -10,7 +8,7 @@ def check_hit_status( amtm: AMTManager, amt_hit_id: str, amt_hit_type_id: str, - reason: Optional[str] = None, + reason: str | None = None, ) -> HitStatus: """ (this used to be called "process_hit") diff --git a/jb/flow/monitoring.py b/jb/flow/monitoring.py index 28f7271..22e9e93 100644 --- a/jb/flow/monitoring.py +++ b/jb/flow/monitoring.py @@ -1,12 +1,11 @@ import socket -from typing import Optional +from generalresearch.currency import USDCent from mypy_boto3_mturk.literals import EventTypeType from jb.config import settings from jb.decorators import influx_client -from generalresearchutils.currency import USDCent -from jb.models.definitions import HitStatus, AssignmentStatus +from jb.models.definitions import AssignmentStatus, HitStatus def write_hit_gauge(status: HitStatus, amt_hit_type_id: str, cnt: int) -> None: @@ -26,8 +25,6 @@ def write_hit_gauge(status: HitStatus, amt_hit_type_id: str, cnt: int) -> None: if influx_client: influx_client.write_points(points=[point]) - return None - def write_assignment_gauge( status: AssignmentStatus, amt_hit_type_id: str, cnt: int @@ -47,11 +44,9 @@ def write_assignment_gauge( if influx_client: influx_client.write_points(points=[point]) - return None - def emit_hit_event( - status: HitStatus, amt_hit_type_id: str, reason: Optional[str] = None + status: HitStatus, amt_hit_type_id: str, reason: str | None = None ) -> None: """ e.g. a HIT was created, Reviewable, etc. We don't have a "created" @@ -77,11 +72,9 @@ def emit_hit_event( if influx_client: influx_client.write_points([point]) - return None - def emit_assignment_event( - status: AssignmentStatus, amt_hit_type_id: str, reason: Optional[str] = None + status: AssignmentStatus, amt_hit_type_id: str, reason: str | None = None ) -> None: """ e.g. an Assignment was accepted/approved/reject @@ -106,8 +99,6 @@ def emit_assignment_event( if influx_client: influx_client.write_points([point]) - return None - def emit_mturk_notification_event( event_type: EventTypeType, amt_hit_type_id: str @@ -133,8 +124,6 @@ def emit_mturk_notification_event( if influx_client: influx_client.write_points([point]) - return None - def emit_error_event(event_type: str, amt_hit_type_id: str) -> None: """ @@ -157,8 +146,6 @@ def emit_error_event(event_type: str, amt_hit_type_id: str) -> None: if influx_client: influx_client.write_points([point]) - return None - def emit_bonus_event(amount: USDCent, amt_hit_type_id: str) -> None: """ @@ -179,5 +166,3 @@ def emit_bonus_event(amount: USDCent, amt_hit_type_id: str) -> None: if influx_client: influx_client.write_points([point]) - - return None diff --git a/jb/flow/setup_tasks.py b/jb/flow/setup_tasks.py index 4664374..f5cda48 100644 --- a/jb/flow/setup_tasks.py +++ b/jb/flow/setup_tasks.py @@ -1,6 +1,5 @@ -from jb.config import TOPIC_ARN, SUBSCRIPTION -from jb.decorators import SNS_CLIENT, AMT_CLIENT -from jb.config import settings +from jb.config import SUBSCRIPTION, TOPIC_ARN, settings +from jb.decorators import AMT_CLIENT, SNS_CLIENT def initial_setup(): diff --git a/jb/flow/tasks.py b/jb/flow/tasks.py index 77825d3..c555021 100644 --- a/jb/flow/tasks.py +++ b/jb/flow/tasks.py @@ -1,18 +1,13 @@ -import logging import time from typing import TypedDict, cast -from generalresearchutils.config import is_debug +from generalresearch.config import is_debug -from jb.decorators import AMTM, HTM, HM, HQM, pg_config +from jb.decorators import AMTM, HM, HQM, HTM, LOG, pg_config from jb.flow.maintenance import check_hit_status -from jb.flow.monitoring import write_hit_gauge, emit_hit_event +from jb.flow.monitoring import emit_hit_event, write_hit_gauge from jb.models.definitions import HitStatus -from jb.models.hit import HitType, HitQuestion, Hit - -logging.basicConfig() -logger = logging.getLogger() -logger.setLevel(logging.INFO) +from jb.models.hit import Hit, HitQuestion, HitType class HitRow(TypedDict): @@ -34,7 +29,7 @@ def check_stale_hits(): params={"status": HitStatus.Assignable.value}, ) for hit in cast(list[HitRow], res): - logging.info(f"check_stale_hits: {hit["amt_hit_id"]}") + LOG.info(f"check_stale_hits: {hit["amt_hit_id"]}") check_hit_status( amtm=AMTM, amt_hit_id=hit["amt_hit_id"], @@ -56,7 +51,7 @@ def check_expired_hits(): params={"status": HitStatus.Assignable.value}, ) for hit in cast(list[HitRow], res): - logging.info(f"check_expired_hits: {hit["amt_hit_id"]}") + LOG.info(f"check_expired_hits: {hit["amt_hit_id"]}") check_hit_status( amtm=AMTM, amt_hit_id=hit["amt_hit_id"], @@ -87,7 +82,7 @@ def refill_hits() -> None: assert hit_type.amt_hit_type_id active_count = HM.get_active_count(hit_type_id=hit_type.id) - logging.info( + LOG.info( f"HitType: {hit_type.amt_hit_type_id}, {hit_type.min_active=}, active_count={active_count}" ) write_hit_gauge( @@ -97,7 +92,7 @@ def refill_hits() -> None: ) if active_count < hit_type.min_active: cnt_todo = hit_type.min_active - active_count - logging.info(f"Refilling {cnt_todo} hits") + LOG.info(f"Refilling {cnt_todo} hits") for _ in range(cnt_todo): create_hit_from_hittype(hit_type) @@ -109,6 +104,6 @@ def refill_hits_task(): check_stale_hits() refill_hits() except Exception as e: - logging.exception(e) + LOG.exception(e) finally: time.sleep(5 * 60) |
