in src/utils/d2c_messaging/src/d2c_messaging.c [203:327]
static void DefaultIoTHubSendReportedStateCompletedCallback(int http_status_code, void* context)
{
Log_Debug("context:0x%x", context);
ADUC_D2C_Message_Processing_Context* message_processing_context = (ADUC_D2C_Message_Processing_Context*)context;
int computed = false;
if (message_processing_context == NULL)
{
Log_Error("context is NULL");
return;
}
if (!message_processing_context->initialized)
{
Log_Warn("Message processing context (0x%x) is not initialized.", message_processing_context);
return;
}
pthread_mutex_lock(&message_processing_context->mutex);
message_processing_context->message.lastHttpStatus = http_status_code;
// It's possible that the message has been destroy by ADUC_D2C_Messaging_Uninit().
// In this case, we just abort here.
if (message_processing_context->message.content == NULL)
{
Log_Debug("Message already been destroy. No op.");
goto done;
}
// Note, stop processing the message if the responseCallback() returned false,
// or http_status_code is >= 200 and < 300.
bool success =
(message_processing_context->message.responseCallback != NULL
&& !message_processing_context->message.responseCallback(http_status_code, message_processing_context))
|| ((http_status_code >= 200 && http_status_code < 300));
time_t previousRetryTimeStamp = message_processing_context->nextRetryTimeStampEpoch;
// Call the responseCallback to allow the message owner to make a decision whether
// to continue trying, and specified the 'nextRetryTimestamp' if needed.
if (success)
{
// The callback indicates that no retries needed.
// We're done with this message.
Log_Debug(
"D2C message processed successfully (t:%d, r:%d, content:0x%x )",
message_processing_context->type,
message_processing_context->retries,
message_processing_context->message.content);
OnMessageProcessingCompleted(&message_processing_context->message, ADUC_D2C_Message_Status_Success);
goto done;
}
if (message_processing_context->nextRetryTimeStampEpoch != previousRetryTimeStamp)
{
// It's possible that the next retry time has been set by the responseCallback(),
// we don't need to do anything here.
SetMessageStatus(&message_processing_context->message, ADUC_D2C_Message_Status_In_Progress);
goto done;
}
if (message_processing_context->retries >= message_processing_context->retryStrategy->maxRetries)
{
Log_Warn(
"Maximum attempt reached (t:%d, r:%d)",
message_processing_context->type,
message_processing_context->retries);
OnMessageProcessingCompleted(
&message_processing_context->message, ADUC_D2C_Message_Status_Max_Retries_Reached);
goto done;
}
for (size_t i = 0; i < message_processing_context->retryStrategy->httpStatusRetryInfoSize; i++)
{
ADUC_D2C_HttpStatus_Retry_Info* info = &message_processing_context->retryStrategy->httpStatusRetryInfo[i];
if (http_status_code >= info->httpStatusMin && http_status_code <= info->httpStatusMax)
{
if (message_processing_context->retries >= info->maxRetry)
{
Log_Warn("Max retries reached (httpStatus:%d)", http_status_code);
OnMessageProcessingCompleted(
&message_processing_context->message, ADUC_D2C_Message_Status_Max_Retries_Reached);
goto done;
}
if (info->retryTimestampCalcFunc == NULL)
{
Log_Debug("Retry timestamp calculator func is not specified. Skipped. (info #%d)", i);
continue;
}
message_processing_context->retries++;
time_t newTime = info->retryTimestampCalcFunc(
info->additionalDelaySecs,
message_processing_context->retries,
message_processing_context->retryStrategy->initialDelayUnitMilliSecs,
message_processing_context->retryStrategy->maxDelaySecs,
message_processing_context->retryStrategy->maxJitterPercent);
Log_Debug(
"Will resend the message in %d second(s) (epoch:%d, t:%d, r:%d, c:0x%x)",
newTime - message_processing_context->nextRetryTimeStampEpoch,
newTime,
message_processing_context->type,
message_processing_context->retries,
message_processing_context->message.content);
message_processing_context->nextRetryTimeStampEpoch = newTime;
SetMessageStatus(&message_processing_context->message, ADUC_D2C_Message_Status_In_Progress);
goto done;
}
}
if (!computed)
{
message_processing_context->nextRetryTimeStampEpoch +=
(time_t)message_processing_context->retryStrategy->fallbackWaitTimeSec;
Log_Warn(
"Failed to calculate the next retry timestamp. Next retry in %lu seconds.",
message_processing_context->retryStrategy->fallbackWaitTimeSec);
SetMessageStatus(&message_processing_context->message, ADUC_D2C_Message_Status_In_Progress);
}
done:
pthread_mutex_unlock(&message_processing_context->mutex);
}