[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[taler-merchant] 01/02: move lookup order for idempotency check into tra
From: |
gnunet |
Subject: |
[taler-merchant] 01/02: move lookup order for idempotency check into transaction scope where it belongs |
Date: |
Mon, 18 Mar 2024 23:09:20 +0100 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository merchant.
commit 63c171f49aa4b3d6d412bf50d07a0fae4beab211
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Mon Mar 18 22:14:48 2024 +0100
move lookup order for idempotency check into transaction scope where it
belongs
---
.../taler-merchant-httpd_private-post-orders.c | 152 ++++++++++++---------
1 file changed, 88 insertions(+), 64 deletions(-)
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c
b/src/backend/taler-merchant-httpd_private-post-orders.c
index 736da1c2..92d35b78 100644
--- a/src/backend/taler-merchant-httpd_private-post-orders.c
+++ b/src/backend/taler-merchant-httpd_private-post-orders.c
@@ -423,6 +423,24 @@ struct OrderContext
* Which product (by offset) is out of stock, UINT_MAX if all were
in-stock.
*/
unsigned int out_of_stock_index;
+
+ /**
+ * Set to a previous claim token *if* @e idempotent
+ * is also true.
+ */
+ struct TALER_ClaimTokenP token;
+
+ /**
+ * Set to true if the order was idempotent and there
+ * was an equivalent one before.
+ */
+ bool idempotent;
+
+ /**
+ * Set to true if the order is in conflict with a
+ * previous order with the same order ID.
+ */
+ bool conflict;
} execute_order;
struct
@@ -661,6 +679,45 @@ execute_transaction (struct OrderContext *oc)
GNUNET_break (0);
return GNUNET_DB_STATUS_HARD_ERROR;
}
+
+ /* Test if we already have an order with this id */
+ {
+ json_t *contract_terms;
+ struct TALER_MerchantPostDataHashP orig_post;
+
+ qs = TMH_db->lookup_order (TMH_db->cls,
+ oc->hc->instance->settings.id,
+ oc->parse_order.order_id,
+ &oc->execute_order.token,
+ &orig_post,
+ &contract_terms);
+ /* If yes, check for idempotency */
+ if (0 > qs)
+ {
+ GNUNET_break (0);
+ TMH_db->rollback (TMH_db->cls);
+ return qs;
+ }
+ if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
+ {
+ TMH_db->rollback (TMH_db->cls);
+ json_decref (contract_terms);
+ /* Comparing the contract terms is sufficient because all the other
+ params get added to it at some point. */
+ if (0 == GNUNET_memcmp (&orig_post,
+ &oc->parse_request.h_post_data))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Order creation idempotent\n");
+ oc->execute_order.idempotent = true;
+ return qs;
+ }
+ GNUNET_break_op (0);
+ oc->execute_order.conflict = true;
+ return qs;
+ }
+ }
+
/* Setup order */
qs = TMH_db->insert_order (TMH_db->cls,
oc->hc->instance->settings.id,
@@ -757,70 +814,6 @@ execute_order (struct OrderContext *oc)
&oc->hc->instance->settings;
enum GNUNET_DB_QueryStatus qs;
- /* Test if we already have an order with this id */
- /* FIXME: this should be done within the main
- transaction! */
- {
- struct TALER_ClaimTokenP token;
- json_t *contract_terms;
- struct TALER_MerchantPostDataHashP orig_post;
-
- TMH_db->preflight (TMH_db->cls);
- qs = TMH_db->lookup_order (TMH_db->cls,
- oc->hc->instance->settings.id,
- oc->parse_order.order_id,
- &token,
- &orig_post,
- &contract_terms);
- /* If yes, check for idempotency */
- if (0 > qs)
- {
- GNUNET_break (0);
- TMH_db->rollback (TMH_db->cls);
- reply_with_error (oc,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GENERIC_DB_FETCH_FAILED,
- "lookup_order");
- return;
- }
- if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == qs)
- {
- MHD_RESULT ret;
-
- json_decref (contract_terms);
- /* Comparing the contract terms is sufficient because all the other
- params get added to it at some point. */
- if (0 == GNUNET_memcmp (&orig_post,
- &oc->parse_request.h_post_data))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Order creation idempotent\n");
- ret = TALER_MHD_REPLY_JSON_PACK (
- oc->connection,
- MHD_HTTP_OK,
- GNUNET_JSON_pack_string ("order_id",
- oc->parse_order.order_id),
- GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_data_varsize (
- "token",
- GNUNET_is_zero (&token)
- ? NULL
- : &token,
- sizeof (token))));
- finalize_order (oc,
- ret);
- return;
- }
- /* This request is not idempotent */
- GNUNET_break_op (0);
- reply_with_error (
- oc,
- MHD_HTTP_CONFLICT,
- TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS,
- oc->parse_order.order_id);
- return;
- }
- }
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Executing database transaction to create order '%s' for
instance '%s'\n",
oc->parse_order.order_id,
@@ -865,6 +858,37 @@ execute_order (struct OrderContext *oc)
return;
}
+ /* DB transaction succeeded, check for idempotent */
+ if (oc->execute_order.idempotent)
+ {
+ MHD_RESULT ret;
+
+ ret = TALER_MHD_REPLY_JSON_PACK (
+ oc->connection,
+ MHD_HTTP_OK,
+ GNUNET_JSON_pack_string ("order_id",
+ oc->parse_order.order_id),
+ GNUNET_JSON_pack_allow_null (
+ GNUNET_JSON_pack_data_varsize (
+ "token",
+ GNUNET_is_zero (&oc->execute_order.token)
+ ? NULL
+ : &oc->execute_order.token,
+ sizeof (oc->execute_order.token))));
+ finalize_order (oc,
+ ret);
+ return;
+ }
+ if (oc->execute_order.conflict)
+ {
+ reply_with_error (
+ oc,
+ MHD_HTTP_CONFLICT,
+ TALER_EC_MERCHANT_PRIVATE_POST_ORDERS_ALREADY_EXISTS,
+ oc->parse_order.order_id);
+ return;
+ }
+
/* DB transaction succeeded, check for out-of-stock */
if (oc->execute_order.out_of_stock_index < UINT_MAX)
{
--
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.