1
+ /*
2
+ Copyright (c) 2024-2025, Oracle and/or its affiliates.
3
+
4
+ Licensed under the Apache License, Version 2.0 (the "License");
5
+ you may not use this file except in compliance with the License.
6
+ You may obtain a copy of the License at
7
+
8
+ https://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ Unless required by applicable law or agreed to in writing, software
11
+ distributed under the License is distributed on an "AS IS" BASIS,
12
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ See the License for the specific language governing permissions and
14
+ limitations under the License.
15
+ */
16
+ import { CacheService } from "../../types" ;
17
+ import { LOGGER } from "../../../logger" ;
18
+ import { globalState } from "../../../globalState" ;
19
+ import { isError } from "../../../utils" ;
20
+ import { removeEntriesOnOverflow } from "./utils" ;
21
+ import { ProjectCacheValue } from "./projectCacheValue" ;
22
+
23
+ export class ProjectCacheService implements CacheService < ProjectCacheValue , String > {
24
+ readonly MAX_KEYS_SIZE : number = 5000 ;
25
+ private removingKeys : boolean = false ;
26
+
27
+ public get = ( key : string ) => {
28
+ try {
29
+ const updatedKey = this . getUpdatedKey ( key ) ;
30
+ const vscGlobalState = globalState . getExtensionContextInfo ( ) . getVscGlobalState ( ) ;
31
+
32
+ const value = vscGlobalState . get < ProjectCacheValue > ( updatedKey ) ;
33
+ if ( value ) {
34
+ this . put ( updatedKey , ProjectCacheValue . fromObject ( { ...value , lastUsed : Date . now ( ) } ) ) ;
35
+ }
36
+
37
+ return value ?. payload ;
38
+ } catch ( err ) {
39
+ LOGGER . error ( `Error while retrieving ${ key } from cache: ${ ( err as Error ) . message } ` ) ;
40
+ return undefined ;
41
+ }
42
+ }
43
+
44
+ public put = async ( key : string , value : ProjectCacheValue ) => {
45
+ try {
46
+ const updatedKey = this . getUpdatedKey ( key ) ;
47
+ const vscGlobalState = globalState . getExtensionContextInfo ( ) . getVscGlobalState ( ) ;
48
+
49
+ await vscGlobalState . update ( updatedKey , value ) ;
50
+ if ( vscGlobalState . keys ( ) . length > this . MAX_KEYS_SIZE ) {
51
+ this . removeOnOverflow ( ) ;
52
+ }
53
+ LOGGER . debug ( `Updating key: ${ key } to ${ value } ` ) ;
54
+
55
+ return true ;
56
+ } catch ( err ) {
57
+ LOGGER . error ( `Error while storing ${ key } in cache: ${ ( err as Error ) . message } ` ) ;
58
+ return false ;
59
+ }
60
+ }
61
+
62
+ public removeOnOverflow = async ( ) => {
63
+ try {
64
+ if ( this . removingKeys ) {
65
+ LOGGER . log ( "Ignoring removing keys request, since it is already in progress" ) ;
66
+ return ;
67
+ }
68
+ this . removingKeys = true ;
69
+
70
+ const vscGlobalState = globalState . getExtensionContextInfo ( ) . getVscGlobalState ( ) ;
71
+ const comparator = ( a : ProjectCacheValue , b : ProjectCacheValue ) => ( a . lastUsed - b . lastUsed ) ;
72
+
73
+ await removeEntriesOnOverflow ( vscGlobalState , ProjectCacheValue . type , comparator ) ;
74
+ } catch ( error ) {
75
+ LOGGER . error ( "Some error occurred while removing keys " + ( isError ( error ) ? error . message : error ) ) ;
76
+ } finally {
77
+ this . removingKeys = false ;
78
+ }
79
+ }
80
+
81
+ // for unit tests needs to be public
82
+ public getUpdatedKey = ( key : string ) => `${ ProjectCacheValue . type } .${ key } ` ;
83
+ }
0 commit comments