1919using System . Collections . Generic ;
2020using System . IO ;
2121using System . Management . Automation . Language ;
22+ using System . Threading . Tasks ;
23+ using System . Threading ;
2224using System . Text . Json ;
2325
24-
25-
2626namespace Microsoft . Azure . PowerShell . Tools . AzPredictor
2727{
2828 /// <summary>
@@ -32,7 +32,13 @@ sealed class ParameterValuePredictor
3232 {
3333 private readonly ConcurrentDictionary < string , string > _localParameterValues = new ConcurrentDictionary < string , string > ( ) ;
3434
35- private readonly Dictionary < string , Dictionary < string , string > > _command_param_to_resource_map ;
35+ private System . Threading . Mutex _mutex = new System . Threading . Mutex ( false , "paramValueHistoryFile_update" ) ;
36+
37+ private readonly Dictionary < string , Dictionary < string , string > > _commandParamToResourceMap ;
38+
39+ private string _paramValueHistoryFilePath = "" ;
40+ private CancellationTokenSource _cancellationTokenSource ;
41+
3642
3743 private ITelemetryClient _telemetryClient ;
3844
@@ -49,17 +55,46 @@ public ParameterValuePredictor(ITelemetryClient telemetryClient)
4955
5056 try
5157 {
52- _command_param_to_resource_map = JsonSerializer . Deserialize < Dictionary < string , Dictionary < string , string > > > ( File . ReadAllText ( mappingFilePath ) , JsonUtilities . DefaultSerializerOptions ) ;
58+ _commandParamToResourceMap = JsonSerializer . Deserialize < Dictionary < string , Dictionary < string , string > > > ( File . ReadAllText ( mappingFilePath ) , JsonUtilities . DefaultSerializerOptions ) ;
5359 }
5460 catch ( Exception e )
5561 {
5662 // We don't want it to crash the module when the file doesn't exist or when it's mal-formatted.
5763 exception = e ;
5864 }
59-
6065 _telemetryClient . OnLoadParameterMap ( new ParameterMapTelemetryData ( exception ) ) ;
66+
67+ String path = Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) ;
68+ string [ ] paths = new string [ ] { path , "Microsoft" , "Windows" , "PowerShell" , "AzPredictor" , "paramValueHistory.json" } ;
69+ _paramValueHistoryFilePath = System . IO . Path . Combine ( paths ) ;
70+ Directory . CreateDirectory ( Path . GetDirectoryName ( _paramValueHistoryFilePath ) ) ;
71+
72+ Task . Run ( ( ) =>
73+ {
74+ if ( System . IO . File . Exists ( _paramValueHistoryFilePath ) )
75+ {
76+ _mutex . WaitOne ( ) ;
77+ try
78+ {
79+ var localParameterValues = JsonSerializer . Deserialize < ConcurrentDictionary < string , string > > ( File . ReadAllText ( _paramValueHistoryFilePath ) , JsonUtilities . DefaultSerializerOptions ) ;
80+ foreach ( var v in localParameterValues )
81+ {
82+ _localParameterValues . AddOrUpdate ( v . Key , key => v . Value , ( key , oldValue ) => oldValue ) ;
83+ }
84+ }
85+ finally
86+ {
87+ _mutex . ReleaseMutex ( ) ;
88+ }
89+ }
90+
91+
92+ } ) ;
93+
6194 }
6295
96+
97+
6398 /// <summary>
6499 /// Process the command from history
65100 /// </summary>
@@ -89,7 +124,7 @@ public string GetParameterValueFromAzCommand(string commandNoun, string paramete
89124 var key = parameterName ;
90125 Dictionary < string , string > commandNounMap = null ;
91126
92- if ( _command_param_to_resource_map ? . TryGetValue ( commandNoun , out commandNounMap ) == true )
127+ if ( _commandParamToResourceMap ? . TryGetValue ( commandNoun , out commandNounMap ) == true )
93128 {
94129 if ( commandNounMap . TryGetValue ( parameterName , out var parameterNameMappedValue ) )
95130 {
@@ -146,7 +181,7 @@ private void ExtractLocalParameters(CommandAst command)
146181 }
147182
148183 Dictionary < string , string > commandNounMap = null ;
149- _command_param_to_resource_map ? . TryGetValue ( commandNoun , out commandNounMap ) ;
184+ _commandParamToResourceMap ? . TryGetValue ( commandNoun , out commandNounMap ) ;
150185
151186 for ( int i = 1 ; i < command . CommandElements . Count ; )
152187 {
@@ -189,8 +224,26 @@ private void ExtractLocalParameters(CommandAst command)
189224 parameterKey = mappedValue ;
190225 }
191226 }
192-
193- _localParameterValues . AddOrUpdate ( parameterKey , parameterValue , ( k , v ) => parameterValue ) ;
227+ _cancellationTokenSource ? . Cancel ( ) ;
228+ _cancellationTokenSource = new CancellationTokenSource ( ) ;
229+ Task . Run ( ( ) =>
230+ {
231+ this . _localParameterValues . AddOrUpdate ( parameterKey , parameterValue , ( k , v ) => parameterValue ) ;
232+ if ( _cancellationTokenSource . IsCancellationRequested )
233+ {
234+ throw new OperationCanceledException ( ) ;
235+ }
236+ String localParameterValuesJson = JsonSerializer . Serialize < ConcurrentDictionary < string , string > > ( _localParameterValues , JsonUtilities . DefaultSerializerOptions ) ;
237+ _mutex . WaitOne ( ) ;
238+ try
239+ {
240+ System . IO . File . WriteAllText ( _paramValueHistoryFilePath , localParameterValuesJson ) ;
241+ }
242+ finally
243+ {
244+ _mutex . ReleaseMutex ( ) ;
245+ }
246+ } ) ;
194247 }
195248 }
196249 }
0 commit comments