mirror of
https://github.com/GSA/notifications-api.git
synced 2026-01-30 06:21:50 -05:00
refactor shared functionality from provider priority logic
This commit is contained in:
@@ -5,7 +5,6 @@ from sqlalchemy import asc, desc, func
|
||||
from flask import current_app
|
||||
|
||||
from app.dao.dao_utils import transactional
|
||||
from app.dao.users_dao import get_user_by_id
|
||||
from app.models import FactBilling, ProviderDetails, ProviderDetailsHistory, SMS_TYPE, User
|
||||
from app import db
|
||||
|
||||
@@ -34,6 +33,42 @@ def dao_get_provider_versions(provider_id):
|
||||
).all()
|
||||
|
||||
|
||||
def _adjust_provider_priority(provider, new_priority):
|
||||
current_app.logger.info(
|
||||
f'Adjusting provider priority - {provider.identifier} going from {provider.priority} to {new_priority}'
|
||||
)
|
||||
provider.priority = new_priority
|
||||
|
||||
# Automatic update so set as notify user
|
||||
provider.created_by_id = current_app.config['NOTIFY_USER_ID']
|
||||
|
||||
# update without commit so that both rows can be changed without ending the transaction
|
||||
# and releasing the for_update lock
|
||||
_update_provider_details_without_commit(provider)
|
||||
|
||||
|
||||
def _get_sms_providers_for_update(time_threshold):
|
||||
"""
|
||||
Returns a list of providers, while holding a for_update lock on the provider details table, guaranteeing that those
|
||||
providers won't change (but can still be read) until you've committed/rolled back your current transaction.
|
||||
|
||||
if any of the providers have been changed recently, it returns an empty list - it's still your responsiblity to
|
||||
release the transaction in that case
|
||||
"""
|
||||
# get current priority of both providers
|
||||
q = ProviderDetails.query.filter(
|
||||
ProviderDetails.notification_type == 'sms',
|
||||
ProviderDetails.active
|
||||
).with_for_update().all()
|
||||
|
||||
# if something updated recently, don't update again. If the updated_at is null, treat it as min time
|
||||
if any((provider.updated_at or datetime.min) > datetime.utcnow() - time_threshold for provider in q):
|
||||
current_app.logger.info(f"Not adjusting providers, providers updated less than {time_threshold} ago.")
|
||||
return []
|
||||
|
||||
return q
|
||||
|
||||
|
||||
@transactional
|
||||
def dao_reduce_sms_provider_priority(identifier, *, time_threshold):
|
||||
"""
|
||||
@@ -41,50 +76,23 @@ def dao_reduce_sms_provider_priority(identifier, *, time_threshold):
|
||||
If either provider has been updated in the last `time_threshold`, then it won't take any action.
|
||||
"""
|
||||
amount_to_reduce_by = 10
|
||||
providers_list = _get_sms_providers_for_update(time_threshold)
|
||||
|
||||
# get current priority of both providers
|
||||
q = ProviderDetails.query.filter(
|
||||
ProviderDetails.notification_type == 'sms',
|
||||
ProviderDetails.active
|
||||
).with_for_update().all()
|
||||
|
||||
providers = {provider.identifier: provider for provider in q}
|
||||
other_identifier = get_alternative_sms_provider(identifier)
|
||||
|
||||
# if something updated recently, don't update again. If the updated_at is null, treat it as min time
|
||||
if any((provider.updated_at or datetime.min) > datetime.utcnow() - time_threshold for provider in q):
|
||||
current_app.logger.info("Not adjusting providers, providers updated less than {} ago.".format(time_threshold))
|
||||
if not providers_list:
|
||||
return
|
||||
|
||||
providers = {provider.identifier: provider for provider in providers_list}
|
||||
other_identifier = get_alternative_sms_provider(identifier)
|
||||
|
||||
reduced_provider = providers[identifier]
|
||||
increased_provider = providers[other_identifier]
|
||||
pre_reduction_priority = reduced_provider.priority
|
||||
pre_increase_priority = increased_provider.priority
|
||||
|
||||
# always keep values between 0 and 100
|
||||
reduced_provider.priority = max(0, reduced_provider.priority - amount_to_reduce_by)
|
||||
increased_provider.priority = min(100, increased_provider.priority + amount_to_reduce_by)
|
||||
reduced_provider_priority = max(0, reduced_provider.priority - amount_to_reduce_by)
|
||||
increased_provider_priority = min(100, increased_provider.priority + amount_to_reduce_by)
|
||||
|
||||
current_app.logger.info('Adjusting provider priority - {} going from {} to {}'.format(
|
||||
reduced_provider.identifier,
|
||||
pre_reduction_priority,
|
||||
reduced_provider.priority,
|
||||
))
|
||||
current_app.logger.info('Adjusting provider priority - {} going from {} to {}'.format(
|
||||
increased_provider.identifier,
|
||||
pre_increase_priority,
|
||||
increased_provider.priority,
|
||||
))
|
||||
|
||||
# Automatic update so set as notify user
|
||||
notify_user = get_user_by_id(current_app.config['NOTIFY_USER_ID'])
|
||||
reduced_provider.created_by_id = notify_user.id
|
||||
increased_provider.created_by_id = notify_user.id
|
||||
|
||||
# update without commit so that both rows can be changed without ending the transaction
|
||||
# and releasing the for_update lock
|
||||
_update_provider_details_without_commit(reduced_provider)
|
||||
_update_provider_details_without_commit(increased_provider)
|
||||
_adjust_provider_priority(reduced_provider, reduced_provider_priority)
|
||||
_adjust_provider_priority(increased_provider, increased_provider_priority)
|
||||
|
||||
|
||||
@transactional
|
||||
@@ -96,36 +104,19 @@ def dao_adjust_provider_priority_back_to_resting_points():
|
||||
amount_to_reduce_by = 10
|
||||
time_threshold = timedelta(hours=1)
|
||||
|
||||
# get current priority of both providers
|
||||
providers = ProviderDetails.query.filter(
|
||||
ProviderDetails.notification_type == 'sms',
|
||||
ProviderDetails.active
|
||||
).with_for_update().all()
|
||||
providers = _get_sms_providers_for_update(time_threshold)
|
||||
|
||||
# if something updated recently, don't update again. If the updated_at is null, treat it as min time
|
||||
if any((provider.updated_at or datetime.min) > datetime.utcnow() - time_threshold for provider in providers):
|
||||
current_app.logger.info("Not adjusting providers, providers updated less than {} ago.".format(time_threshold))
|
||||
return
|
||||
|
||||
# Automatic update so set as notify user
|
||||
notify_user = get_user_by_id(current_app.config['NOTIFY_USER_ID'])
|
||||
for provider in providers:
|
||||
target = current_app.config['SMS_PROVIDER_RESTING_POINTS'][provider.identifier]
|
||||
current = provider.priority
|
||||
|
||||
if current != target:
|
||||
if current > target:
|
||||
provider.priority = max(provider.priority - amount_to_reduce_by, target)
|
||||
new_priority = max(target, provider.priority - amount_to_reduce_by)
|
||||
else:
|
||||
provider.priority = min(provider.priority + amount_to_reduce_by, target)
|
||||
new_priority = min(target, provider.priority + amount_to_reduce_by)
|
||||
|
||||
provider.created_by_id = notify_user.id
|
||||
_update_provider_details_without_commit(provider)
|
||||
current_app.logger.info('Adjusting provider priority - {} going from {} to {}'.format(
|
||||
provider.identifier,
|
||||
current,
|
||||
provider.priority,
|
||||
))
|
||||
_adjust_provider_priority(provider, new_priority)
|
||||
|
||||
|
||||
def get_provider_details_by_notification_type(notification_type, supports_international=False):
|
||||
|
||||
Reference in New Issue
Block a user