Idempotent Charge Requests
Networks drop responses, so clients retry. A payments API that treats every retry as a new request charges people twice. The standard defence is an idempotency key: the client sends the same key with every attempt of one charge, and the server answers a retry with the original result instead of charging again.
You are given the charge requests in time order. Request i arrives at second times[i] with key keys[i] and asks to charge customer customers[i] the amount amounts[i]. Charges get ids 1, 2, 3, ... in the order they are created. Answer each request:
- If its key created a charge less than 24 hours (86,400 seconds) ago and the customer and amount are the same as that charge's, it is a retry: answer
"replayed:<id>"with that charge's id and create nothing. - If its key created a charge less than 24 hours ago but the customer or the amount differs, the key is being misused: answer
"conflict"and change nothing. - Otherwise (the key is new, or its charge was created 86,400 seconds ago or more), create a new charge, answer
"created:<id>", and from now on the key refers to this new charge.
Keys are case-sensitive. Return the answers in order.
Example
Key k1 creates charge 1 at second 0. Its retry at second 5 is replayed; at second 6 the same key arrives with a different amount, a conflict. Key k2 creates charge 2. At second 86,399 k1 is still within 24 hours of charge 1 and is replayed, but at 86,400 the 24 hours are up, so it creates charge 3. At 86,401 k1 refers to charge 3, and a different customer is a conflict.
The answer is ["created:1", "replayed:1", "conflict", "created:2", "replayed:1", "created:3", "conflict"].
[ "[0,5,6,7,86399,86400,86401]", "[\"k1\",\"k1\",\"k1\",\"k2\",\"k1\",\"k1\",\"k1\"]", "[7,7,7,7,7,7,8]", "[500,500,600,500,500,500,500]" ]
Explanation. The example.
[ "[0,1,2]", "[\"a\",\"a\",\"a\"]", "[1,2,1]", "[100,100,100]" ]
Explanation. A conflict changes nothing.
[ "[0,0]", "[\"x\",\"y\"]", "[1,1]", "[100,100]" ]
Explanation. Different keys are different charges, even with the same details.
[ "[0,100000,100001,100002]", "[\"k\",\"k\",\"k\",\"k\"]", "[1,2,2,1]", "[100,999,999,100]" ]
Explanation. An expired key starts afresh, with whatever details it now carries.
[ "[42]", "[\"only\"]", "[3]", "[1]" ]
Explanation. A single request.
[ "[0,1]", "[\"Key\",\"key\"]", "[1,1]", "[10,10]" ]
Explanation. Keys are case-sensitive.
[ "[10,10,10]", "[\"k\",\"k\",\"k\"]", "[1,1,1]", "[1,1,1]" ]
Explanation. Retries in the same second.
[ "[0,1,86400,86400,86401,172800]", "[\"a\",\"b\",\"a\",\"b\",\"b\",\"a\"]", "[1,1,1,1,1,1]", "[5,5,5,5,5,5]" ]
Explanation. Keys expire independently, each 24 hours after its own charge.
Follow-up: Two retries of the same new key arrive at two different API servers in the same millisecond, and both see the key as new. What would you store, and where, so that only one of them creates the charge while the other waits for its result?
- `1 <= times.length <= 10^5`, and the four arrays have the same length. - `0 <= times[i] <= 10^9`, and `times` is non-decreasing. - `keys[i]` has 1 to 64 letters, digits, `-` and `_`. - `1 <= customers[i] <= 10^9` - `1 <= amounts[i] <= 10^9`
- Views
- 2