this repo has no description
at main 170 lines 3.9 kB view raw
1import birl 2import gleam/bool 3import gleam/dict 4import gleam/dynamic 5import gleam/dynamic/decode 6import gleam/http/response 7import gleam/json 8import gleam/list 9import gleam/option 10import gleam/order 11import gleam/string_tree 12import models/count_provider 13import models/payment_request.{type PaymentRequest, PaymentRequest} 14import redis 15import valkyrie/resp 16import web/server 17import wisp 18 19fn decode_payment_body( 20 body: dynamic.Dynamic, 21 cb: fn(PaymentRequest) -> wisp.Response, 22) { 23 let decoder = { 24 use correlation <- decode.field("correlationId", decode.string) 25 use amount <- decode.field("amount", decode.float) 26 27 decode.success(PaymentRequest( 28 correlation_id: correlation, 29 amount: amount, 30 requested_at: birl.now(), 31 provider: option.None, 32 )) 33 } 34 case decode.run(body, decoder) { 35 Ok(body) -> cb(body) 36 Error(_) -> wisp.bad_request() 37 } 38} 39 40pub fn handle_payment_post( 41 req: wisp.Request, 42 ctx: server.Context, 43) -> response.Response(wisp.Body) { 44 use json <- wisp.require_json(req) 45 use body <- decode_payment_body(json) 46 47 let data_to_insert = 48 body 49 |> payment_request.to_json 50 |> json.to_string 51 |> list.wrap 52 53 let assert Ok(_) = 54 ctx.valkye_conn 55 |> redis.enqueue_payments(data_to_insert) 56 57 wisp.no_content() 58} 59 60fn get_all_payments_response( 61 default: count_provider.CountProvider, 62 fallback: count_provider.CountProvider, 63) -> json.Json { 64 [ 65 #("default", count_provider.to_json(default)), 66 #("fallback", count_provider.to_json(fallback)), 67 ] 68 |> json.object 69} 70 71fn all_payments_empty_body() { 72 let body = 73 get_all_payments_response( 74 count_provider.new("default"), 75 count_provider.new("fallback"), 76 ) 77 |> json.to_string_tree 78 79 wisp.ok() 80 |> wisp.json_body(body) 81} 82 83pub fn get_all_payments( 84 req: wisp.Request, 85 ctx: server.Context, 86) -> response.Response(wisp.Body) { 87 let params = 88 req 89 |> wisp.get_query 90 |> list.map(fn(param) { 91 let #(key, value) = param 92 let assert Ok(v) = value |> birl.parse 93 94 #(key, v) 95 }) 96 |> dict.from_list 97 98 use <- bool.lazy_guard( 99 when: !dict.has_key(params, "from"), 100 return: all_payments_empty_body, 101 ) 102 103 use <- bool.lazy_guard( 104 when: !dict.has_key(params, "to"), 105 return: all_payments_empty_body, 106 ) 107 108 let assert Ok(from) = dict.get(params, "from") 109 let assert Ok(to) = dict.get(params, "to") 110 111 let data_in_redis = case redis.get_all_saved_data(ctx.valkye_conn) { 112 Ok(data) -> 113 data 114 |> dict.values 115 |> list.filter_map(fn(value) { 116 let assert resp.BulkString(v) = value 117 let assert Ok(json_data) = payment_request.from_json_string(v) 118 119 use <- bool.guard( 120 when: birl.compare(json_data.requested_at, from) == order.Lt, 121 return: Error(Nil), 122 ) 123 use <- bool.guard( 124 when: birl.compare(json_data.requested_at, to) == order.Gt, 125 return: Error(Nil), 126 ) 127 128 Ok(json_data) 129 }) 130 Error(_) -> [] 131 } 132 133 use <- bool.guard( 134 when: data_in_redis == [], 135 return: wisp.no_content() 136 |> wisp.json_body(string_tree.from_string("[]")), 137 ) 138 139 let grouped_by_provider = 140 data_in_redis 141 |> list.group(by: fn(data) { 142 case data { 143 payment_request.PaymentRequest(provider: option.Some("default"), ..) -> 144 "default" 145 _ -> "fallback" 146 } 147 }) 148 149 let default_requests = 150 count_provider.new("default") 151 |> count_provider.count_provider(grouped_by_provider) 152 let fallback_requests = 153 count_provider.new("fallback") 154 |> count_provider.count_provider(grouped_by_provider) 155 156 wisp.ok() 157 |> wisp.json_body( 158 get_all_payments_response(default_requests, fallback_requests) 159 |> json.to_string_tree, 160 ) 161} 162 163pub fn purge_payments( 164 _req: wisp.Request, 165 ctx: server.Context, 166) -> response.Response(wisp.Body) { 167 case redis.delete_saved_data(ctx.valkye_conn) { 168 _ -> wisp.no_content() 169 } 170}