1/*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16type FetchId = number;
17type ItemIndex = number;
18
19// eslint-disable-next-line @typescript-eslint/no-unused-vars
20class FetchingRegistry {
21  private readonly fetches = new Map<FetchId, ItemIndex>();
22  private fetching = new Map<ItemIndex, FetchId>();
23  private readonly fetchesBefore = new Map<ItemIndex, number>();
24
25  private fetchCounter = 0;
26
27  registerFetch(index: ItemIndex): FetchId {
28    let fetchId = this.fetching.get(index);
29    if (fetchId !== undefined) {
30      return fetchId;
31    }
32
33    fetchId = ++this.fetchCounter;
34    this.fetching.set(index, fetchId);
35    this.fetches.set(fetchId, index);
36    this.fetchesBefore.set(index, this.fetches.size);
37
38    return fetchId;
39  }
40
41  getItem(fetchId: FetchId): ItemIndex {
42    return this.fetches.get(fetchId);
43  }
44
45  deleteFetch(fetchId: FetchId): void {
46    const index = this.fetches.get(fetchId);
47    if (index !== undefined) {
48      this.fetching.delete(index);
49      this.fetches.delete(fetchId);
50    }
51  }
52
53  deleteFetchByItem(index: ItemIndex): void {
54    const fetchId = this.fetching.get(index);
55    if (fetchId !== undefined) {
56      this.fetching.delete(index);
57      this.fetches.delete(fetchId);
58    }
59  }
60
61  isFetchingItem(index: ItemIndex): boolean {
62    return this.fetching.has(index);
63  }
64
65  incrementAllIndexesGreaterThen(value: number): void {
66    this.offsetAllIndexesGreaterThen(value, 1);
67  }
68
69  getAllIndexes(): Set<number> {
70    const set = new Set<number>();
71    this.fetching.forEach((fetchId, itemIndex) => set.add(itemIndex));
72    return set;
73  }
74
75  getFetchesCount(): number {
76    return this.fetches.size;
77  }
78
79  isFetchLatecomer(index: ItemIndex, threshold: number): boolean {
80    return this.fetchesBefore.get(index) > threshold;
81  }
82
83  private offsetAllIndexesGreaterThen(value: number, offset: number): void {
84    const newFetching = new Map<ItemIndex, FetchId>();
85    this.fetches.forEach((index, fetchId) => {
86      const toSet = index > value ? index + offset : index;
87      newFetching.set(toSet, fetchId);
88      this.fetches.set(fetchId, toSet);
89    });
90    this.fetching = newFetching;
91  }
92
93  decrementAllIndexesGreaterThen(value: number): void {
94    this.offsetAllIndexesGreaterThen(value, -1);
95  }
96}
97