Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2023 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file backenddb/pg_lookup_pending_webhooks.c
18 : * @brief Implementation of the lookup_pending_webhooks function for Postgres
19 : * @author Iván Ávalos
20 : */
21 : #include "platform.h"
22 : #include <taler/taler_error_codes.h>
23 : #include <taler/taler_dbevents.h>
24 : #include <taler/taler_pq_lib.h>
25 : #include "pg_lookup_pending_webhooks.h"
26 : #include "pg_helper.h"
27 :
28 : /**
29 : * Context used for lookup_pending_webhooks_cb().
30 : */
31 : struct LookupPendingWebhookContext
32 : {
33 : /**
34 : * Function to call with the results.
35 : */
36 : TALER_MERCHANTDB_PendingWebhooksCallback cb;
37 :
38 : /**
39 : * Closure for @a cb.
40 : */
41 : void *cb_cls;
42 :
43 : /**
44 : * Did database result extraction fail?
45 : */
46 : bool extract_failed;
47 : };
48 :
49 :
50 : /**
51 : * Function to be called with the results of a SELECT statement
52 : * that has returned @a num_results results about webhook.
53 : *
54 : * @param[in,out] cls of type `struct LookupPendingWebhookContext *`
55 : * @param result the postgres result
56 : * @param num_results the number of results in @a result
57 : */
58 : static void
59 78 : lookup_pending_webhooks_cb (void *cls,
60 : PGresult *result,
61 : unsigned int num_results)
62 : {
63 78 : struct LookupPendingWebhookContext *pwlc = cls;
64 :
65 80 : for (unsigned int i = 0; i < num_results; i++)
66 : {
67 : uint64_t webhook_pending_serial;
68 : struct GNUNET_TIME_Absolute next_attempt;
69 : uint32_t retries;
70 : char *url;
71 : char *http_method;
72 2 : char *header = NULL;
73 2 : char *body = NULL;
74 2 : struct GNUNET_PQ_ResultSpec rs[] = {
75 2 : GNUNET_PQ_result_spec_uint64 ("webhook_pending_serial",
76 : &webhook_pending_serial),
77 2 : GNUNET_PQ_result_spec_absolute_time ("next_attempt",
78 : &next_attempt),
79 2 : GNUNET_PQ_result_spec_uint32 ("retries",
80 : &retries),
81 2 : GNUNET_PQ_result_spec_string ("url",
82 : &url),
83 2 : GNUNET_PQ_result_spec_string ("http_method",
84 : &http_method),
85 2 : GNUNET_PQ_result_spec_allow_null (
86 : GNUNET_PQ_result_spec_string ("header",
87 : &header),
88 : NULL),
89 2 : GNUNET_PQ_result_spec_allow_null (
90 : GNUNET_PQ_result_spec_string ("body",
91 : &body),
92 : NULL),
93 : GNUNET_PQ_result_spec_end
94 : };
95 :
96 2 : if (GNUNET_OK !=
97 2 : GNUNET_PQ_extract_result (result,
98 : rs,
99 : i))
100 : {
101 0 : GNUNET_break (0);
102 0 : pwlc->extract_failed = true;
103 0 : return;
104 : }
105 2 : pwlc->cb (pwlc->cb_cls,
106 : webhook_pending_serial,
107 : next_attempt,
108 : retries,
109 : url,
110 : http_method,
111 : header,
112 : body);
113 2 : GNUNET_PQ_cleanup_result (rs);
114 : }
115 : }
116 :
117 :
118 : enum GNUNET_DB_QueryStatus
119 41 : TMH_PG_lookup_pending_webhooks (void *cls,
120 : TALER_MERCHANTDB_PendingWebhooksCallback cb,
121 : void *cb_cls)
122 : {
123 41 : struct PostgresClosure *pg = cls;
124 41 : struct LookupPendingWebhookContext pwlc = {
125 : .cb = cb,
126 : .cb_cls = cb_cls,
127 : .extract_failed = false,
128 : };
129 41 : struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
130 41 : struct GNUNET_PQ_QueryParam params_null[] = {
131 41 : GNUNET_PQ_query_param_absolute_time (&now),
132 : GNUNET_PQ_query_param_end
133 : };
134 :
135 : enum GNUNET_DB_QueryStatus qs;
136 :
137 41 : check_connection (pg);
138 41 : PREPARE (pg,
139 : "lookup_pending_webhooks",
140 : "SELECT"
141 : " webhook_pending_serial"
142 : ",next_attempt"
143 : ",retries"
144 : ",url"
145 : ",http_method"
146 : ",header"
147 : ",body"
148 : " FROM merchant_pending_webhooks"
149 : " WHERE next_attempt <= $1"
150 : " ORDER BY next_attempt ASC"
151 : );
152 :
153 41 : qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
154 : "lookup_pending_webhooks",
155 : params_null,
156 : &lookup_pending_webhooks_cb,
157 : &pwlc);
158 :
159 41 : if (pwlc.extract_failed)
160 0 : return GNUNET_DB_STATUS_HARD_ERROR;
161 41 : return qs;
162 : }
163 :
164 :
165 : enum GNUNET_DB_QueryStatus
166 37 : TMH_PG_lookup_future_webhook (void *cls,
167 : TALER_MERCHANTDB_PendingWebhooksCallback cb,
168 : void *cb_cls)
169 : {
170 37 : struct PostgresClosure *pg = cls;
171 37 : struct LookupPendingWebhookContext pwlc = {
172 : .cb = cb,
173 : .cb_cls = cb_cls,
174 : .extract_failed = false,
175 : };
176 37 : struct GNUNET_PQ_QueryParam params_null[] = {
177 : GNUNET_PQ_query_param_end
178 : };
179 :
180 : enum GNUNET_DB_QueryStatus qs;
181 :
182 37 : check_connection (pg);
183 37 : PREPARE (pg,
184 : "lookup_future_webhook",
185 : "SELECT"
186 : " webhook_pending_serial"
187 : ",next_attempt"
188 : ",retries"
189 : ",url"
190 : ",http_method"
191 : ",header"
192 : ",body"
193 : " FROM merchant_pending_webhooks"
194 : " ORDER BY next_attempt ASC LIMIT 1"
195 : );
196 :
197 37 : qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
198 : "lookup_future_webhook",
199 : params_null,
200 : &lookup_pending_webhooks_cb,
201 : &pwlc);
202 :
203 37 : if (pwlc.extract_failed)
204 0 : return GNUNET_DB_STATUS_HARD_ERROR;
205 37 : return qs;
206 : }
207 :
208 :
209 : enum GNUNET_DB_QueryStatus
210 0 : TMH_PG_lookup_all_webhooks (void *cls,
211 : const char *instance_id,
212 : uint64_t min_row,
213 : uint32_t max_results,
214 : TALER_MERCHANTDB_PendingWebhooksCallback cb,
215 : void *cb_cls)
216 : {
217 0 : struct PostgresClosure *pg = cls;
218 0 : struct LookupPendingWebhookContext pwlc = {
219 : .cb = cb,
220 : .cb_cls = cb_cls,
221 : .extract_failed = false,
222 : };
223 0 : uint64_t max_results64 = max_results;
224 0 : struct GNUNET_PQ_QueryParam params[] = {
225 0 : GNUNET_PQ_query_param_string (instance_id),
226 0 : GNUNET_PQ_query_param_uint64 (&min_row),
227 0 : GNUNET_PQ_query_param_uint64 (&max_results64),
228 : GNUNET_PQ_query_param_end
229 : };
230 :
231 : enum GNUNET_DB_QueryStatus qs;
232 :
233 0 : check_connection (pg);
234 0 : PREPARE (pg,
235 : "lookup_all_webhooks",
236 : " SELECT"
237 : " webhook_pending_serial"
238 : ",next_attempt"
239 : ",retries"
240 : ",url"
241 : ",http_method"
242 : ",header"
243 : ",body"
244 : " FROM merchant_pending_webhooks"
245 : " JOIN merchant_instances"
246 : " USING (merchant_serial)"
247 : " WHERE merchant_instances.merchant_id=$1"
248 : " AND webhook_pending_serial > $2"
249 : " ORDER BY webhook_pending_serial"
250 : " ASC LIMIT $3");
251 :
252 0 : qs = GNUNET_PQ_eval_prepared_multi_select (pg->conn,
253 : "lookup_all_webhooks",
254 : params,
255 : &lookup_pending_webhooks_cb,
256 : &pwlc);
257 :
258 0 : if (pwlc.extract_failed)
259 0 : return GNUNET_DB_STATUS_HARD_ERROR;
260 0 : return qs;
261 : }
|