Skip to content

Commit

Permalink
Merge branch 'handle-fiscal-bot-invalid-statuses' into 'master'
Browse files Browse the repository at this point in the history
fix fiscal_bot invalid data status responses, fix check_for_response_file

See merge request cdb/prozorro_tasks!200
  • Loading branch information
Volodymyr Kovalenko committed Feb 25, 2021
2 parents dcf7c52 + a2c38d2 commit d015c55
Show file tree
Hide file tree
Showing 7 changed files with 528 additions and 44 deletions.
3 changes: 3 additions & 0 deletions environment_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ def environ_list(name, sep=","):
# we've decided to use the counter first sign to distinct our requests from different environments
# for prod the will be 0000001, 0000002, ..., for sandbox - 9000001, 9000002, ...
FISCAL_BOT_ENV_NUMBER = int(os.environ.get("FISCAL_BOT_ENV_NUMBER", 0))
FISCAL_BOT_CHECK_RECEIPT_TASKS_COLLECTION = os.environ.get(
"FISCAL_BOT_CHECK_RECEIPT_TASKS_COLLECTION", "fiscal_bot_check_receipt_tasks"
)

SENTRY_DSN = os.environ.get("SENTRY_DSN", None)
SENTRY_ENVIRONMENT = os.environ.get("SENTRY_ENVIRONMENT", None)
Expand Down
7 changes: 7 additions & 0 deletions fiscal_bot/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@
WORKING_DAYS_BEFORE_REQUEST_AGAIN = 2
REQUEST_MAX_RETRIES = 2

NUMBER_OF_WORKING_DAYS_FOR_REQUEST_RETRY_MAPPING = {
0: 10,
1: 8,
2: 6
}
assert len(NUMBER_OF_WORKING_DAYS_FOR_REQUEST_RETRY_MAPPING.keys())-1 == REQUEST_MAX_RETRIES

FISCAL_BOT_START_DATE = os.environ.get("FISCAL_BOT_START_DATE", "2019-07-01")
REQUEST_DOC_VERSION = int(os.environ.get("FISCAL_BOT_REQUEST_DOC_VERSION", 2))

Expand Down
126 changes: 105 additions & 21 deletions fiscal_bot/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,24 @@
IDENTIFICATION_SCHEME, DOC_TYPE,
WORKING_DAYS_BEFORE_REQUEST_AGAIN, REQUEST_MAX_RETRIES,
WORKING_TIME,
NUMBER_OF_WORKING_DAYS_FOR_REQUEST_RETRY_MAPPING,
)
from fiscal_bot.fiscal_api import build_receipt_request
from fiscal_bot.settings import FISCAL_BOT_START_DATE
from fiscal_bot.utils import (
save_check_receipt_task_info,
get_check_receipt_tasks_info_by_tender_id,
get_check_receipt_task_info_by_id,
)
from tasks_utils.datetime import get_now, get_working_datetime, working_days_count_since
from tasks_utils.tasks import upload_to_doc_service
from tasks_utils.results_db import get_task_result, save_task_result
from tasks_utils.settings import RETRY_REQUESTS_EXCEPTIONS, DEFAULT_HEADERS
from tasks_utils.requests import get_filename_from_response, get_task_retry_logger_method
from tasks_utils.requests import (
get_filename_from_response,
get_task_retry_logger_method,
get_exponential_request_retry_countdown,
)
from datetime import timedelta
import requests
import base64
Expand Down Expand Up @@ -122,7 +132,7 @@ def prepare_receipt_request(self, supplier, requests_reties=0):
)


@app.task(bind=True, max_retries=10)
@app.task(bind=True, max_retries=50)
@formatter.omit(["request_data"])
def send_request_receipt(self, request_data, filename, supplier, requests_reties):
task_args = supplier, requests_reties
Expand All @@ -141,15 +151,37 @@ def send_request_receipt(self, request_data, filename, supplier, requests_reties
else:
if response.status_code != 200:
logger.error("Unsuccessful status code: {} {}".format(response.status_code, response.text),
extra={"MESSAGE_ID": "FISCAL_API_POST_REQUEST_ERROR"})
extra={"MESSAGE_ID": "FISCAL_API_POST_INVALID_STATUS_CODE_RESPONSE_ERROR"})
self.retry(countdown=response.headers.get('Retry-After', DEFAULT_RETRY_AFTER))
else:
data = response.json()

if data["status"] != "OK":
logger.error("Getting receipt failed: {} {}".format(response.status_code, response.text),
extra={"MESSAGE_ID": "FISCAL_API_POST_REQUEST_ERROR"})
return
if data["status"] != "ERROR_DB":
logger.info(
"Getting receipt status: {} {}, retrying ...".format(
response.status_code, response.text
),
extra={"MESSAGE_ID": "FISCAL_API_POST_DATA_STATUS_ERROR_RESPONSE"}
)
self.retry(
countdown=get_exponential_request_retry_countdown(self, response)
)
else:
if "CallableStatementCallback" in data["message"]:
logger.error(
"Getting receipt failed: {} {}".format(response.status_code, response.text),
extra={"MESSAGE_ID": "FISCAL_API_POST_CALLABLE_STATEMENT_CALLBACK_ERROR_RESPONSE"}
)
self.retry(
countdown=get_exponential_request_retry_countdown(self, response)
)
else:
logger.error(
"Getting receipt failed: {} {}".format(response.status_code, response.text),
extra={"MESSAGE_ID": "FISCAL_API_POST_DATA_STATUS_ERROR_DB_RESPONSE"}
)
return
else:
uid = save_task_result(self, data, task_args)
logger.info(
Expand Down Expand Up @@ -271,27 +303,66 @@ def prepare_check_request(self, uid, supplier, request_time, requests_reties):
@app.task(bind=True, max_retries=None)
@formatter.omit(["request_data"])
def check_for_response_file(self, request_data, supplier, request_time, requests_reties):
""""
* Checking for response file. In case no answer after WORKING_DAYS_BEFORE_REQUEST_AGAIN ->
called new prepare_receipt_request.
* If successful response appears in any task with same tenderID -> Stop all check_for_response_file tasks for
specified tenderID.
requests_reties / days | 1 2 3 4 5 6 7 8 9 10
-----------------------|---------------------
initial task | + + + + + + + + + +
1st task | + + + + + + + +
2nd task | + + + + + +
"""

task_id = self.request.id
tender_id = supplier["tender_id"]
tender_check_receipts_tasks = get_check_receipt_tasks_info_by_tender_id(tender_id)

if any([record["receiptFileSuccessfullySaved"] for record in tender_check_receipts_tasks]):
logger.warning(
"Receipt file for {} tender has been already obtained by another task. Stop checking.".format(tender_id),
extra={"MESSAGE_ID": "FISCAL_API_STOP_CHECKING_DUE_TO_ANOTHER_SUCCESSFUL_TASK"}
)
return

try:
number_of_working_days_for_check = NUMBER_OF_WORKING_DAYS_FOR_REQUEST_RETRY_MAPPING[requests_reties]
except KeyError:
logger.error(extra={"MESSAGE_ID": "UNEXPECTED_REQUEST_RETRY_NUMBER"})
return

days_passed = working_days_count_since(request_time, working_weekends_enabled=True)
check_receipt_task_info = get_check_receipt_task_info_by_id(task_id)

if check_receipt_task_info:
has_called_new_check_receipt_task = check_receipt_task_info['hasCalledNewCheckReceiptTask']
else:
has_called_new_check_receipt_task = False

if days_passed > WORKING_DAYS_BEFORE_REQUEST_AGAIN:
if not has_called_new_check_receipt_task:

if requests_reties < REQUEST_MAX_RETRIES:
prepare_receipt_request.delay(
supplier=supplier,
requests_reties=requests_reties + 1
)
logger.warning(
"Request retry scheduled",
extra={"MESSAGE_ID": "FISCAL_REQUEST_RETRY_SCHEDULED"}
)
else:
logger.warning(
"Additional requests number {} exceeded".format(REQUEST_MAX_RETRIES),
extra={"MESSAGE_ID": "FISCAL_REQUEST_RETRY_EXCEED"}
)
if requests_reties < REQUEST_MAX_RETRIES:
save_check_receipt_task_info(
tender_id, task_id, has_called_new_check_receipt_task=True
)
prepare_receipt_request.delay(
supplier=supplier,
requests_reties=requests_reties + 1
)
logger.warning(
"Request retry scheduled for {} days".format(number_of_working_days_for_check),
extra={"MESSAGE_ID": "FISCAL_REQUEST_RETRY_SCHEDULED"}
)
else:
logger.warning(
"Additional requests number {} exceeded".format(REQUEST_MAX_RETRIES),
extra={"MESSAGE_ID": "FISCAL_REQUEST_RETRY_EXCEED"}
)

else:
if days_passed <= number_of_working_days_for_check:
try:
response = requests.post(
'{}/cabinet/public/api/exchange/kvt_by_id'.format(FISCAL_API_HOST),
Expand Down Expand Up @@ -331,6 +402,12 @@ def check_for_response_file(self, request_data, supplier, request_time, requests
else:
for kvt in data["kvtList"]:
if kvt["finalKvt"]:
save_check_receipt_task_info(
tender_id, task_id,
has_called_new_check_receipt_task=has_called_new_check_receipt_task,
receipt_file_successfully_saved=True
)

decode_and_save_data.delay(
kvt["kvtFname"],
kvt["kvtBase64"],
Expand All @@ -343,3 +420,10 @@ def check_for_response_file(self, request_data, supplier, request_time, requests
),
extra={"MESSAGE_ID": "FISCAL_API_KVT_FOUND"}
)
else:
logger.warning(
"{}/{} number of working days exceed for receipt request retry №{}. Stop checking.".format(
days_passed, number_of_working_days_for_check, requests_reties+1),
extra={"MESSAGE_ID": "FISCAL_REQUEST_WORKING_DAYS_RETRY_EXCEED"}
)

Loading

0 comments on commit d015c55

Please sign in to comment.