-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathregion_service.ts
115 lines (88 loc) · 3.84 KB
/
region_service.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import AsyncLock from 'async-lock';
import { Region, RegionRequestOptions } from './region';
import { AdapterOption } from './adapter';
export interface S3IdEndpoint {
s3Id: string,
s3Endpoint: string,
}
export type GetAllRegionsOptions = RegionRequestOptions;
const defaultCacheKey = 'DEFAULT';
const regionCache: Map<string, Region[]> = new Map<string, Region[]>();
const queryRegionLock = new AsyncLock();
export class RegionService {
constructor(private readonly adapterOption: AdapterOption) {
}
async getAllRegions(options?: GetAllRegionsOptions): Promise<Region[]> {
if (this.adapterOption.regions.length > 0) {
return this.adapterOption.regions;
}
const cacheKey = this.adapterOption.ucUrl ?? defaultCacheKey;
let regions = regionCache.get(cacheKey);
const isCacheValid = regions?.every(r => r.validated);
if (regions && isCacheValid) {
return regions;
}
regions = await queryRegionLock.acquire(cacheKey, async (): Promise<Region[]> => {
const regions = regionCache.get(cacheKey);
const isCacheValid = regions?.every(r => r.validated);
if (regions && isCacheValid) {
return regions;
}
return await Region.getAll({
accessKey: this.adapterOption.accessKey,
secretKey: this.adapterOption.secretKey,
ucUrl: this.adapterOption.ucUrl,
timeout: options?.timeout,
retry: options?.retry,
retryDelay: options?.retryDelay,
appName: this.adapterOption.appName,
appVersion: this.adapterOption.appVersion,
uplogBufferSize: this.adapterOption.uplogBufferSize,
requestCallback: this.adapterOption.requestCallback,
responseCallback: this.adapterOption.responseCallback,
stats: options?.stats,
});
});
regionCache.set(cacheKey, regions);
return regions;
}
clearCache() {
regionCache.clear();
}
async getS3Endpoint(s3RegionId?: string, options?: GetAllRegionsOptions): Promise<S3IdEndpoint> {
let queryCondition: (region: Region) => boolean;
if (s3RegionId) {
queryCondition = (region) => region.s3Id === s3RegionId && region.s3Urls.length > 0;
} else {
queryCondition = (region) => !!region.s3Id && region.s3Urls.length > 0;
}
const regions = await this.getAllRegions(options);
const region: Region | undefined = regions.find(queryCondition);
if (!region) {
if (s3RegionId) {
throw new Error(`Cannot find region endpoint url of ${s3RegionId}`);
} else {
throw new Error('Cannot find valid region endpoint url');
}
}
return { s3Id: region.s3Id, s3Endpoint: region.s3Urls[0] };
}
async fromKodoRegionIdToS3Id(regionId: string, options?: GetAllRegionsOptions): Promise<string> {
const regions = await this.getAllRegions(options);
const queryCondition: (region: Region) => boolean = (region) => region.id === regionId;
const region: Region | undefined = regions.find(queryCondition);
if (!region?.s3Id) {
throw new Error(`Cannot find region s3 id of ${regionId}`);
}
return region.s3Id;
}
async fromS3IdToKodoRegionId(s3Id: string, options?: GetAllRegionsOptions): Promise<string> {
const regions = await this.getAllRegions(options);
const queryCondition: (region: Region) => boolean = (region) => region.s3Id === s3Id;
const region: Region | undefined = regions.find(queryCondition);
if (!region?.id) {
throw new Error(`Cannot find region id of ${s3Id}`);
}
return region.id;
}
}