gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-merchant] 81/277: fix/complete inventory management logic


From: gnunet
Subject: [taler-merchant] 81/277: fix/complete inventory management logic
Date: Sun, 05 Jul 2020 20:49:54 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository merchant.

commit 9e90a4432b414382344ea525a34af27e661523f4
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat May 2 22:03:52 2020 +0200

    fix/complete inventory management logic
---
 src/backend/taler-merchant-httpd_exchanges.c       | 143 ++++++++++++++-------
 .../taler-merchant-httpd_post-orders-ID-abort.c    |   4 +-
 .../taler-merchant-httpd_post-orders-ID-claim.c    |  11 --
 src/backenddb/plugin_merchantdb_postgres.c         |  57 +++++++-
 src/include/taler_merchantdb_plugin.h              |   4 +-
 src/lib/merchant_api_post_order_abort.c            |  24 +++-
 6 files changed, 169 insertions(+), 74 deletions(-)

diff --git a/src/backend/taler-merchant-httpd_exchanges.c 
b/src/backend/taler-merchant-httpd_exchanges.c
index f874bb9..ef5bde9 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -22,6 +22,7 @@
 #include "platform.h"
 #include <taler/taler_json_lib.h>
 #include "taler-merchant-httpd_exchanges.h"
+#include "taler-merchant-httpd.h"
 
 
 /**
@@ -726,6 +727,70 @@ wire_task_cb (void *cls)
 }
 
 
+/**
+ * We failed downloading /keys from @a exchange. Tell clients
+ * about our failure, abort pending operations and retry later.
+ *
+ * @param exchange exchange that failed
+ * @param hr details about the HTTP reply
+ * @param compat version compatibility data
+ */
+static void
+fail_and_retry (struct Exchange *exchange,
+                const struct TALER_EXCHANGE_HttpResponse *hr,
+                enum TALER_EXCHANGE_VersionCompatibility compat)
+{
+  struct TMH_EXCHANGES_FindOperation *fo;
+
+  exchange->pending = GNUNET_YES;
+  if (NULL != exchange->wire_request)
+  {
+    TALER_EXCHANGE_wire_cancel (exchange->wire_request);
+    exchange->wire_request = NULL;
+  }
+  if (NULL != exchange->wire_task)
+  {
+    GNUNET_SCHEDULER_cancel (exchange->wire_task);
+    exchange->wire_task = NULL;
+  }
+  while (NULL != (fo = exchange->fo_head))
+  {
+    fo->fc (fo->fc_cls,
+            hr,
+            NULL,
+            NULL,
+            GNUNET_NO);
+    TMH_EXCHANGES_find_exchange_cancel (fo);
+  }
+  if (TALER_EXCHANGE_VC_INCOMPATIBLE_NEWER == compat)
+  {
+    /* Log hard error: we likely need admin help! */
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Exchange `%s' runs an incompatible more recent version of the 
Taler protocol. Will not retry. This client may need to be updated.\n",
+                exchange->url);
+    /* Theoretically, the exchange could downgrade,
+       but let's not be too aggressive about retries
+       on this one. */
+    exchange->retry_delay = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_HOURS,
+                                                      exchange->retry_delay);
+  }
+  exchange->retry_delay = RETRY_BACKOFF (exchange->retry_delay);
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Failed to fetch /keys from `%s': %d/%u, retrying in %s\n",
+              exchange->url,
+              (int) hr->ec,
+              hr->http_status,
+              GNUNET_STRINGS_relative_time_to_string (exchange->retry_delay,
+                                                      GNUNET_YES));
+  GNUNET_assert (NULL == exchange->retry_task);
+  exchange->first_retry = GNUNET_TIME_relative_to_absolute (
+    exchange->retry_delay);
+  exchange->retry_task = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay,
+                                                       &retry_exchange,
+                                                       exchange);
+}
+
+
 /**
  * Function called with information about who is auditing
  * a particular exchange and what key the exchange is using.
@@ -754,54 +819,9 @@ keys_mgmt_cb (void *cls,
 
   if (NULL == keys)
   {
-    struct TMH_EXCHANGES_FindOperation *fo;
-
-    exchange->pending = GNUNET_YES;
-    if (NULL != exchange->wire_request)
-    {
-      TALER_EXCHANGE_wire_cancel (exchange->wire_request);
-      exchange->wire_request = NULL;
-    }
-    if (NULL != exchange->wire_task)
-    {
-      GNUNET_SCHEDULER_cancel (exchange->wire_task);
-      exchange->wire_task = NULL;
-    }
-    while (NULL != (fo = exchange->fo_head))
-    {
-      fo->fc (fo->fc_cls,
-              hr,
-              NULL,
-              NULL,
-              GNUNET_NO);
-      TMH_EXCHANGES_find_exchange_cancel (fo);
-    }
-    if (TALER_EXCHANGE_VC_INCOMPATIBLE_NEWER == compat)
-    {
-      /* Log hard error: we likely need admin help! */
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Exchange `%s' runs an incompatible more recent version of 
the Taler protocol. Will not retry. This client may need to be updated.\n",
-                  exchange->url);
-      /* Theoretically, the exchange could downgrade,
-         but let's not be too aggressive about retries
-         on this one. */
-      exchange->retry_delay = GNUNET_TIME_relative_max (GNUNET_TIME_UNIT_HOURS,
-                                                        exchange->retry_delay);
-    }
-    exchange->retry_delay = RETRY_BACKOFF (exchange->retry_delay);
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Failed to fetch /keys from `%s': %d/%u, retrying in %s\n",
-                exchange->url,
-                (int) hr->ec,
-                hr->http_status,
-                GNUNET_STRINGS_relative_time_to_string (exchange->retry_delay,
-                                                        GNUNET_YES));
-    GNUNET_assert (NULL == exchange->retry_task);
-    exchange->first_retry = GNUNET_TIME_relative_to_absolute (
-      exchange->retry_delay);
-    exchange->retry_task = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay,
-                                                         &retry_exchange,
-                                                         exchange);
+    fail_and_retry (exchange,
+                    hr,
+                    compat);
     return;
   }
   if ( (GNUNET_YES == exchange->trusted) &&
@@ -830,8 +850,31 @@ keys_mgmt_cb (void *cls,
                   exchange->url);
     }
   }
-  // FIXME: go over keys->sign_keys and STORE
-  // all of those into our database!
+
+  /* store exchange online signing keys in our DB */
+  for (unsigned int i = 0; i<keys->num_sign_keys; i++)
+  {
+    struct TALER_EXCHANGE_SigningPublicKey *sign_key = &keys->sign_keys[i];
+    enum GNUNET_DB_QueryStatus qs;
+
+    TMH_db->preflight (TMH_db->cls);
+    qs = TMH_db->insert_exchange_signkey (TMH_db->cls,
+                                          &keys->master_pub,
+                                          &sign_key->key,
+                                          sign_key->valid_from,
+                                          sign_key->valid_until,
+                                          sign_key->valid_legal,
+                                          &sign_key->master_sig);
+    /* 0 is OK, we may already have the key in the DB! */
+    if (0 > qs)
+    {
+      GNUNET_break (0);
+      fail_and_retry (exchange,
+                      hr,
+                      compat);
+      return;
+    }
+  }
 
   expire = TALER_EXCHANGE_check_keys_current (exchange->conn,
                                               GNUNET_NO,
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c 
b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
index 08773a7..4c7960e 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c
@@ -741,7 +741,7 @@ begin_transaction (struct AbortContext *ac)
         /* Payment is complete, refuse to abort. */
         TMH_db->rollback (TMH_db->cls);
         resume_abort_with_error (ac,
-                                 MHD_HTTP_FORBIDDEN,
+                                 MHD_HTTP_PRECONDITION_FAILED,
                                  
TALER_EC_ABORT_REFUND_REFUSED_PAYMENT_COMPLETE,
                                  "Payment was complete, refusing to abort");
         return;
@@ -753,7 +753,7 @@ begin_transaction (struct AbortContext *ac)
     {
       GNUNET_break_op (0);
       resume_abort_with_error (ac,
-                               MHD_HTTP_BAD_REQUEST,
+                               MHD_HTTP_FORBIDDEN,
                                TALER_EC_ABORT_CONTRACT_HASH_MISSMATCH,
                                "Provided hash does not match order on file");
       return;
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-claim.c 
b/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
index 17ef013..80c178b 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-claim.c
@@ -103,17 +103,6 @@ claim_order (const char *instance_id,
       *contract_terms = NULL;
       return qs;
     }
-    qs = TMH_db->delete_order (TMH_db->cls,
-                               instance_id,
-                               order_id);
-    if (0 >= qs)
-    {
-      GNUNET_break (0);
-      TMH_db->rollback (TMH_db->cls);
-      json_decref (*contract_terms);
-      *contract_terms = NULL;
-      return qs;
-    }
     qs = TMH_db->commit (TMH_db->cls);
     if (0 > qs)
       return qs;
diff --git a/src/backenddb/plugin_merchantdb_postgres.c 
b/src/backenddb/plugin_merchantdb_postgres.c
index 8f1a864..784650a 100644
--- a/src/backenddb/plugin_merchantdb_postgres.c
+++ b/src/backenddb/plugin_merchantdb_postgres.c
@@ -1863,7 +1863,8 @@ postgres_lookup_refunds (void *cls,
 
 /**
  * Mark contract as paid and store the current @a session_id
- * for which the contract was paid.
+ * for which the contract was paid. Deletes the underlying order
+ * and marks the locked stocks of the order as sold.
  *
  * @param cls closure
  * @param instance_id instance to mark contract as paid for
@@ -1884,6 +1885,12 @@ postgres_mark_contract_paid (void *cls,
     GNUNET_PQ_query_param_string (session_id),
     GNUNET_PQ_query_param_end
   };
+  struct GNUNET_PQ_QueryParam uparams[] = {
+    GNUNET_PQ_query_param_string (instance_id),
+    GNUNET_PQ_query_param_auto_from_type (h_contract_terms),
+    GNUNET_PQ_query_param_end
+  };
+  enum GNUNET_DB_QueryStatus qs;
 
   /* no preflight check here, run in transaction by caller! */
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1891,9 +1898,19 @@ postgres_mark_contract_paid (void *cls,
               GNUNET_h2s (h_contract_terms),
               instance_id,
               session_id);
+  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                           "mark_contract_paid",
+                                           params);
+  if (qs <= 0)
+    return qs;
+  qs = GNUNET_PQ_eval_prepared_non_select (pg->conn,
+                                           "mark_inventory_sold",
+                                           uparams);
+  if (qs < 0)
+    return qs; /* 0: no inventory management, that's OK! */
   return GNUNET_PQ_eval_prepared_non_select (pg->conn,
-                                             "mark_contract_paid",
-                                             params);
+                                             "delete_completed_order",
+                                             uparams);
 }
 
 
@@ -5472,6 +5489,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             "   FULL OUTER JOIN ed ON TRUE"
                             "  WHERE h_contract_terms=$2",
                             16),
+    /* for postgres_lookup_refunds() */
     GNUNET_PQ_make_prepare ("lookup_refunds",
                             "SELECT"
                             " coin_pub"
@@ -5487,6 +5505,7 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             "           FROM merchant_instances"
                             "          WHERE merchant_id=$1))",
                             2),
+    /* for postgres_mark_contract_paid() */
     GNUNET_PQ_make_prepare ("mark_contract_paid",
                             "UPDATE merchant_contract_terms SET"
                             " paid=TRUE"
@@ -5497,6 +5516,38 @@ libtaler_plugin_merchantdb_postgres_init (void *cls)
                             "        FROM merchant_instances"
                             "       WHERE merchant_id=$1)",
                             3),
+    /* for postgres_mark_contract_paid() */
+    GNUNET_PQ_make_prepare ("mark_inventory_sold",
+                            "UPDATE merchant_inventory SET"
+                            " total_sold=total_sold + order_locks.total_locked"
+                            " FROM (SELECT total_locked,product_serial"
+                            "       FROM merchant_order_locks"
+                            "       WHERE order_serial="
+                            "       (SELECT order_serial"
+                            "          FROM merchant_contract_terms"
+                            "         WHERE h_contract_terms=$2"
+                            "           AND merchant_serial="
+                            "           (SELECT merchant_serial"
+                            "              FROM merchant_instances"
+                            "             WHERE merchant_id=$1))"
+                            "       ) AS order_locks"
+                            " WHERE merchant_inventory.product_serial"
+                            "             =order_locks.product_serial",
+                            2),
+    /* for postgres_mark_contract_paid() */
+    GNUNET_PQ_make_prepare ("delete_completed_order",
+                            "WITH md AS"
+                            "  (SELECT merchant_serial"
+                            "     FROM merchant_instances"
+                            "    WHERE merchant_id=$1) "
+                            "DELETE"
+                            " FROM merchant_orders"
+                            " WHERE order_serial="
+                            "       (SELECT order_serial"
+                            "          FROM merchant_contract_terms"
+                            "          JOIN md USING (merchant_serial)"
+                            "         WHERE h_contract_terms=$2)",
+                            2),
     /* for postgres_refund_coin() */
     GNUNET_PQ_make_prepare ("refund_coin",
                             "INSERT INTO merchant_refunds"
diff --git a/src/include/taler_merchantdb_plugin.h 
b/src/include/taler_merchantdb_plugin.h
index d2e7801..a58cb7d 100644
--- a/src/include/taler_merchantdb_plugin.h
+++ b/src/include/taler_merchantdb_plugin.h
@@ -779,6 +779,7 @@ struct TALER_MERCHANTDB_Plugin
                   const char *instance_id,
                   const char *order_id);
 
+
   /**
    * Retrieve order given its @a order_id and the @a instance_id.
    *
@@ -1016,7 +1017,8 @@ struct TALER_MERCHANTDB_Plugin
 
   /**
    * Mark contract as paid and store the current @a session_id
-   * for which the contract was paid.
+   * for which the contract was paid. Deletes the underlying order
+   * and marks the locked stocks of the order as sold.
    *
    * @param cls closure
    * @param instance_id instance to mark contract as paid for
diff --git a/src/lib/merchant_api_post_order_abort.c 
b/src/lib/merchant_api_post_order_abort.c
index 9b45e38..6ee20f9 100644
--- a/src/lib/merchant_api_post_order_abort.c
+++ b/src/lib/merchant_api_post_order_abort.c
@@ -122,8 +122,13 @@ check_abort_refund (struct TALER_MERCHANT_OrderAbortHandle 
*ph,
     GNUNET_break_op (0);
     return GNUNET_SYSERR;
   }
+  if (! json_is_array (refunds))
+  {
+    GNUNET_break_op (0);
+    GNUNET_JSON_parse_free (spec);
+    return GNUNET_SYSERR;
+  }
   num_refunds = json_array_size (refunds);
-  // FIXME: test for array first!
   {
     struct TALER_MERCHANT_AbortedCoin res[GNUNET_NZL (num_refunds)];
 
@@ -380,11 +385,18 @@ handle_abort_finished (void *cls,
        merchant is buggy (or API version conflict); just
        pass JSON reply to the application */
     break;
-  case MHD_HTTP_CONFLICT:
+  case MHD_HTTP_FORBIDDEN:
     hr.ec = TALER_JSON_get_error_code (json);
     hr.hint = TALER_JSON_get_error_hint (json);
     break;
-  case MHD_HTTP_FORBIDDEN:
+  case MHD_HTTP_NOT_FOUND:
+    hr.ec = TALER_JSON_get_error_code (json);
+    hr.hint = TALER_JSON_get_error_hint (json);
+    /* Nothing really to verify, this should never
+ happen, we should pass the JSON reply to the
+       application */
+    break;
+  case MHD_HTTP_REQUEST_TIMEOUT:
     hr.ec = TALER_JSON_get_error_code (json);
     hr.hint = TALER_JSON_get_error_hint (json);
     /* Nothing really to verify, merchant says one of
@@ -392,12 +404,10 @@ handle_abort_finished (void *cls,
        this should never happen, we should pass the JSON
        reply to the application */
     break;
-  case MHD_HTTP_NOT_FOUND:
+  case MHD_HTTP_PRECONDITION_FAILED:
+    /* Our *payment* already succeeded fully. */
     hr.ec = TALER_JSON_get_error_code (json);
     hr.hint = TALER_JSON_get_error_hint (json);
-    /* Nothing really to verify, this should never
- happen, we should pass the JSON reply to the
-       application */
     break;
   case MHD_HTTP_FAILED_DEPENDENCY:
     TALER_MERCHANT_parse_error_details_ (json,

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]