@@ -215,6 +215,61 @@ protected function hit(string $key, int $timestamp): void
215215 $ this ->count ++;
216216 }
217217
218+ /**
219+ * @param string $key
220+ * @param int $timestamp
221+ * @param int $value
222+ * @return void
223+ *
224+ * @throws AuthorizationException|Structure|\Exception|\Throwable
225+ */
226+ protected function set (string $ key , int $ timestamp , int $ value ): void
227+ {
228+ $ timestamp = $ this ->toDateTime ($ timestamp );
229+ Authorization::skip (function () use ($ timestamp , $ key , $ value ) {
230+ $ data = $ this ->db ->findOne (self ::COLLECTION , [
231+ Query::equal ('key ' , [$ key ]),
232+ Query::equal ('time ' , [$ timestamp ]),
233+ ]);
234+
235+ if ($ data ->isEmpty ()) {
236+ $ data = [
237+ '$permissions ' => [],
238+ 'key ' => $ key ,
239+ 'time ' => $ timestamp ,
240+ 'count ' => $ value ,
241+ '$collection ' => self ::COLLECTION ,
242+ ];
243+
244+ try {
245+ $ this ->db ->createDocument (self ::COLLECTION , new Document ($ data ));
246+ } catch (Duplicate $ e ) {
247+ // Duplicate in case of race condition - update existing document
248+ $ data = $ this ->db ->findOne (self ::COLLECTION , [
249+ Query::equal ('key ' , [$ key ]),
250+ Query::equal ('time ' , [$ timestamp ]),
251+ ]);
252+
253+ if (!$ data ->isEmpty ()) {
254+ /** @var Document $data */
255+ $ this ->db ->updateDocument (self ::COLLECTION , $ data ->getId (), new Document ([
256+ 'count ' => $ value ,
257+ ]));
258+ } else {
259+ throw new \Exception ('Unable to find abuse tracking document after race condition handling ' );
260+ }
261+ }
262+ } else {
263+ /** @var Document $data */
264+ $ this ->db ->updateDocument (self ::COLLECTION , $ data ->getId (), new Document ([
265+ 'count ' => $ value ,
266+ ]));
267+ }
268+ });
269+
270+ $ this ->count = $ value ;
271+ }
272+
218273 /**
219274 * Get abuse logs
220275 *
0 commit comments