def test_purge_signup_tokens(db): with auth_api_session() as (auth_api, metadata_interceptor): reply = auth_api.Signup(auth_pb2.SignupReq(email="*****@*****.**")) # send email process_job() with session_scope() as session: signup_token = session.query(SignupToken).one() signup_token.expiry = func.now() assert session.query(SignupToken).count() == 1 queue_job(BackgroundJobType.purge_signup_tokens, empty_pb2.Empty()) # purge tokens process_job() with session_scope() as session: assert session.query(SignupToken).count() == 0 with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.completed).count() == 2 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.completed).count() == 0
def test_purge_password_reset_tokens(db): user, api_token = generate_user() with session_scope() as session: password_reset_token = PasswordResetToken(token=urlsafe_secure_token(), user=user, expiry=now()) session.add(password_reset_token) assert session.execute( select(func.count()).select_from( PasswordResetToken)).scalar_one() == 1 queue_job(BackgroundJobType.purge_password_reset_tokens, empty_pb2.Empty()) process_job() with session_scope() as session: assert session.execute( select(func.count()).select_from( PasswordResetToken)).scalar_one() == 0 with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.completed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.completed)). scalar_one() == 0)
def test_job_retry(db): queue_job(BackgroundJobType.purge_login_tokens, empty_pb2.Empty()) called_count = 0 def mock_handler(payload): nonlocal called_count called_count += 1 raise Exception() MOCK_JOBS = { BackgroundJobType.purge_login_tokens: (empty_pb2.Empty, mock_handler), } create_prometheus_server(registry=job_process_registry, port=8001) with patch("couchers.jobs.worker.JOBS", MOCK_JOBS): process_job() with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.error)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.error)). scalar_one() == 0) session.execute(select( BackgroundJob)).scalar_one().next_attempt_after = func.now() process_job() with session_scope() as session: session.execute(select( BackgroundJob)).scalar_one().next_attempt_after = func.now() process_job() with session_scope() as session: session.execute(select( BackgroundJob)).scalar_one().next_attempt_after = func.now() process_job() with session_scope() as session: session.execute(select( BackgroundJob)).scalar_one().next_attempt_after = func.now() process_job() with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.failed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.failed)).scalar_one( ) == 0) _check_job_counter("purge_login_tokens", "error", "4", "Exception") _check_job_counter("purge_login_tokens", "failed", "5", "Exception")
def queue_email(sender_name, sender_email, recipient, subject, plain, html): payload = jobs_pb2.SendEmailPayload( sender_name=sender_name, sender_email=sender_email, recipient=recipient, subject=subject, plain=plain, html=html, ) queue_job( job_type=BackgroundJobType.send_email, payload=payload, )
def test_enforce_community_memberships(db): queue_job(BackgroundJobType.enforce_community_membership, empty_pb2.Empty()) process_job() with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.completed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.completed)). scalar_one() == 0)
def test_purge_account_deletion_tokens(db): user, api_token = generate_user() user2, api_token2 = generate_user() user3, api_token3 = generate_user() with session_scope() as session: """ 3 cases: 1) Token is valid 2) Token expired but account retrievable 3) Account is irretrievable (and expired) """ account_deletion_tokens = [ AccountDeletionToken(token=urlsafe_secure_token(), user=user, expiry=now() - timedelta(hours=2)), AccountDeletionToken(token=urlsafe_secure_token(), user=user2, expiry=now()), AccountDeletionToken(token=urlsafe_secure_token(), user=user3, expiry=now() + timedelta(hours=5)), ] for token in account_deletion_tokens: session.add(token) assert session.execute( select(func.count()).select_from( AccountDeletionToken)).scalar_one() == 3 queue_job(BackgroundJobType.purge_account_deletion_tokens, empty_pb2.Empty()) process_job() with session_scope() as session: assert session.execute( select(func.count()).select_from( AccountDeletionToken)).scalar_one() == 1 with session_scope() as session: assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state == BackgroundJobState.completed)).scalar_one() == 1) assert (session.execute( select(func.count()).select_from(BackgroundJob).where( BackgroundJob.state != BackgroundJobState.completed)). scalar_one() == 0)
def _run_job_and_schedule(sched, schedule_id): job_type, frequency = SCHEDULE[schedule_id] logger.info(f"Processing job of type {job_type}") # wake ourselves up after frequency sched.enter( frequency.total_seconds(), 1, _run_job_and_schedule, argument=( sched, schedule_id, ), ) # queue the job queue_job(job_type, empty_pb2.Empty())
def notify( *, user_id, topic, key, action, title, link, avatar_key=None, icon=None, content=None, ): """ Queues a notification given the notification and a target, i.e. a tuple (user_id, topic, key), and an action. Notifications are sent to user identified by user_id, and are collapsed/grouped based on the combination of (topic, key). For example, topic may be "chat" for a group chat/direct message, and the key might be the chat id; so that messages in the same group chat show up in one group. The action is a simple identifier describing the action that caused the notification. For the above example, the action might be "add_admin" if the notification was caused by another user adding an admin into the gorup chat. Each different notification type should have its own action. """ with session_scope() as session: notification = Notification( user_id=user_id, topic_action=enum_from_topic_action[topic, action], key=key, avatar_key=avatar_key, icon=icon, title=title, content=content, link=link, ) session.add(notification) session.flush() notification_id = notification.id queue_job( job_type=BackgroundJobType.handle_notification, payload=jobs_pb2.HandleNotificationPayload( notification_id=notification_id, ), )
def test_purge_login_tokens(db): user, api_token = generate_user() with session_scope() as session: login_token, expiry_text = new_login_token(session, user) login_token.expiry = func.now() assert session.query(LoginToken).count() == 1 queue_job(BackgroundJobType.purge_login_tokens, empty_pb2.Empty()) process_job() with session_scope() as session: assert session.query(LoginToken).count() == 0 with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.completed).count() == 1 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.completed).count() == 0
def _add_message_to_subscription(session, subscription, **kwargs): """ Creates a new message for a subscription, from the user whose subscription that is. Updates last seen message id Specify the keyword args for Message """ message = Message(conversation=subscription.group_chat.conversation, author_id=subscription.user_id, **kwargs) session.add(message) session.flush() subscription.last_seen_message_id = message.id # generate notifications in the background queue_job( job_type=BackgroundJobType.generate_message_notifications, payload=jobs_pb2.GenerateMessageNotificationsPayload( message_id=message.id, ), ) return message
def test_job_retry(db): queue_job(BackgroundJobType.purge_login_tokens, empty_pb2.Empty()) called_count = 0 def mock_handler(payload): nonlocal called_count called_count += 1 raise Exception() MOCK_JOBS = { BackgroundJobType.purge_login_tokens: (empty_pb2.Empty, mock_handler), } with patch("couchers.jobs.worker.JOBS", MOCK_JOBS): process_job() with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.error).count() == 1 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.error).count() == 0 session.query(BackgroundJob).one().next_attempt_after = func.now() process_job() with session_scope() as session: session.query(BackgroundJob).one().next_attempt_after = func.now() process_job() with session_scope() as session: session.query(BackgroundJob).one().next_attempt_after = func.now() process_job() with session_scope() as session: session.query(BackgroundJob).one().next_attempt_after = func.now() process_job() with session_scope() as session: assert session.query(BackgroundJob).filter( BackgroundJob.state == BackgroundJobState.failed).count() == 1 assert session.query(BackgroundJob).filter( BackgroundJob.state != BackgroundJobState.failed).count() == 0