3
3
using System . Collections . Generic ;
4
4
using System . IO ;
5
5
using System . Linq ;
6
+ using System . Threading ;
6
7
using System . Threading . Tasks ;
7
8
using Flow . Launcher . Infrastructure ;
8
9
using Flow . Launcher . Infrastructure . Logger ;
@@ -52,13 +53,14 @@ public static void Save()
52
53
}
53
54
}
54
55
55
- public static void ReloadData ( )
56
+ public static async Task ReloadData ( )
56
57
{
57
- foreach ( var plugin in AllPlugins )
58
+ await Task . WhenAll ( AllPlugins . Select ( plugin => plugin . Plugin switch
58
59
{
59
- var reloadablePlugin = plugin . Plugin as IReloadable ;
60
- reloadablePlugin ? . ReloadData ( ) ;
61
- }
60
+ IReloadable p => Task . Run ( p . ReloadData ) ,
61
+ IAsyncReloadable p => p . ReloadDataAsync ( ) ,
62
+ _ => Task . CompletedTask ,
63
+ } ) . ToArray ( ) ) ;
62
64
}
63
65
64
66
static PluginManager ( )
@@ -86,50 +88,62 @@ public static void LoadPlugins(PluginsSettings settings)
86
88
/// Call initialize for all plugins
87
89
/// </summary>
88
90
/// <returns>return the list of failed to init plugins or null for none</returns>
89
- public static void InitializePlugins ( IPublicAPI api )
91
+ public static async Task InitializePlugins ( IPublicAPI api )
90
92
{
91
93
API = api ;
92
94
var failedPlugins = new ConcurrentQueue < PluginPair > ( ) ;
93
- Parallel . ForEach ( AllPlugins , pair =>
95
+
96
+ var InitTasks = AllPlugins . Select ( pair => Task . Run ( async delegate
94
97
{
95
98
try
96
99
{
97
- var milliseconds = Stopwatch . Debug ( $ "|PluginManager.InitializePlugins|Init method time cost for < { pair . Metadata . Name } >" , ( ) =>
100
+ var milliseconds = pair . Plugin switch
98
101
{
99
- pair . Plugin . Init ( new PluginInitContext
100
- {
101
- CurrentPluginMetadata = pair . Metadata ,
102
- API = API
103
- } ) ;
104
- } ) ;
102
+ IAsyncPlugin plugin
103
+ => await Stopwatch . DebugAsync ( $ "|PluginManager.InitializePlugins|Init method time cost for <{ pair . Metadata . Name } >",
104
+ ( ) => plugin . InitAsync ( new PluginInitContext ( pair . Metadata , API ) ) ) ,
105
+ IPlugin plugin
106
+ => Stopwatch . Debug ( $ "|PluginManager.InitializePlugins|Init method time cost for <{ pair . Metadata . Name } >",
107
+ ( ) => plugin . Init ( new PluginInitContext ( pair . Metadata , API ) ) ) ,
108
+ _ => throw new ArgumentException ( ) ,
109
+ } ;
105
110
pair . Metadata . InitTime += milliseconds ;
106
- Log . Info ( $ "|PluginManager.InitializePlugins|Total init cost for <{ pair . Metadata . Name } > is <{ pair . Metadata . InitTime } ms>") ;
111
+ Log . Info (
112
+ $ "|PluginManager.InitializePlugins|Total init cost for <{ pair . Metadata . Name } > is <{ pair . Metadata . InitTime } ms>") ;
107
113
}
108
114
catch ( Exception e )
109
115
{
110
116
Log . Exception ( nameof ( PluginManager ) , $ "Fail to Init plugin: { pair . Metadata . Name } ", e ) ;
111
- pair . Metadata . Disabled = true ;
117
+ pair . Metadata . Disabled = true ;
112
118
failedPlugins . Enqueue ( pair ) ;
113
119
}
114
- } ) ;
120
+ } ) ) ;
121
+
122
+ await Task . WhenAll ( InitTasks ) ;
115
123
116
124
_contextMenuPlugins = GetPluginsForInterface < IContextMenu > ( ) ;
117
125
foreach ( var plugin in AllPlugins )
118
126
{
119
- if ( IsGlobalPlugin ( plugin . Metadata ) )
120
- GlobalPlugins . Add ( plugin ) ;
121
-
122
- // Plugins may have multiple ActionKeywords, eg. WebSearch
123
- plugin . Metadata . ActionKeywords
124
- . Where ( x => x != Query . GlobalPluginWildcardSign )
125
- . ToList ( )
126
- . ForEach ( x => NonGlobalPlugins [ x ] = plugin ) ;
127
+ foreach ( var actionKeyword in plugin . Metadata . ActionKeywords )
128
+ {
129
+ switch ( actionKeyword )
130
+ {
131
+ case Query . GlobalPluginWildcardSign :
132
+ GlobalPlugins . Add ( plugin ) ;
133
+ break ;
134
+ default :
135
+ NonGlobalPlugins [ actionKeyword ] = plugin ;
136
+ break ;
137
+ }
138
+ }
127
139
}
128
140
129
141
if ( failedPlugins . Any ( ) )
130
142
{
131
143
var failed = string . Join ( "," , failedPlugins . Select ( x => x . Metadata . Name ) ) ;
132
- API . ShowMsg ( $ "Fail to Init Plugins", $ "Plugins: { failed } - fail to load and would be disabled, please contact plugin creator for help", "" , false ) ;
144
+ API . ShowMsg ( $ "Fail to Init Plugins",
145
+ $ "Plugins: { failed } - fail to load and would be disabled, please contact plugin creator for help",
146
+ "" , false ) ;
133
147
}
134
148
}
135
149
@@ -146,24 +160,46 @@ public static List<PluginPair> ValidPluginsForQuery(Query query)
146
160
}
147
161
}
148
162
149
- public static List < Result > QueryForPlugin ( PluginPair pair , Query query )
163
+ public static async Task < List < Result > > QueryForPlugin ( PluginPair pair , Query query , CancellationToken token )
150
164
{
151
165
var results = new List < Result > ( ) ;
152
166
try
153
167
{
154
168
var metadata = pair . Metadata ;
155
- var milliseconds = Stopwatch . Debug ( $ "|PluginManager.QueryForPlugin|Cost for { metadata . Name } ", ( ) =>
169
+
170
+ long milliseconds = - 1L ;
171
+
172
+ switch ( pair . Plugin )
156
173
{
157
- results = pair . Plugin . Query ( query ) ?? new List < Result > ( ) ;
158
- UpdatePluginMetadata ( results , metadata , query ) ;
159
- } ) ;
174
+ case IAsyncPlugin plugin :
175
+ milliseconds = await Stopwatch . DebugAsync ( $ "|PluginManager.QueryForPlugin|Cost for { metadata . Name } ",
176
+ async ( ) => results = await plugin . QueryAsync ( query , token ) . ConfigureAwait ( false ) ) ;
177
+ break ;
178
+ case IPlugin plugin :
179
+ await Task . Run ( ( ) => milliseconds = Stopwatch . Debug ( $ "|PluginManager.QueryForPlugin|Cost for { metadata . Name } ",
180
+ ( ) => results = plugin . Query ( query ) ) , token ) . ConfigureAwait ( false ) ;
181
+ break ;
182
+ default :
183
+ throw new ArgumentOutOfRangeException ( ) ;
184
+ }
185
+ token . ThrowIfCancellationRequested ( ) ;
186
+ UpdatePluginMetadata ( results , metadata , query ) ;
187
+
160
188
metadata . QueryCount += 1 ;
161
- metadata . AvgQueryTime = metadata . QueryCount == 1 ? milliseconds : ( metadata . AvgQueryTime + milliseconds ) / 2 ;
189
+ metadata . AvgQueryTime =
190
+ metadata . QueryCount == 1 ? milliseconds : ( metadata . AvgQueryTime + milliseconds ) / 2 ;
191
+ token . ThrowIfCancellationRequested ( ) ;
192
+ }
193
+ catch ( OperationCanceledException )
194
+ {
195
+ // null will be fine since the results will only be added into queue if the token hasn't been cancelled
196
+ return results = null ;
162
197
}
163
198
catch ( Exception e )
164
199
{
165
200
Log . Exception ( $ "|PluginManager.QueryForPlugin|Exception for plugin <{ pair . Metadata . Name } > when query <{ query } >", e ) ;
166
201
}
202
+
167
203
return results ;
168
204
}
169
205
@@ -182,11 +218,6 @@ public static void UpdatePluginMetadata(List<Result> results, PluginMetadata met
182
218
}
183
219
}
184
220
185
- private static bool IsGlobalPlugin ( PluginMetadata metadata )
186
- {
187
- return metadata . ActionKeywords . Contains ( Query . GlobalPluginWildcardSign ) ;
188
- }
189
-
190
221
/// <summary>
191
222
/// get specified plugin, return null if not found
192
223
/// </summary>
@@ -222,16 +253,19 @@ public static List<Result> GetContextMenusForPlugin(Result result)
222
253
}
223
254
catch ( Exception e )
224
255
{
225
- Log . Exception ( $ "|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{ pluginPair . Metadata . Name } >", e ) ;
256
+ Log . Exception (
257
+ $ "|PluginManager.GetContextMenusForPlugin|Can't load context menus for plugin <{ pluginPair . Metadata . Name } >",
258
+ e ) ;
226
259
}
227
260
}
261
+
228
262
return results ;
229
263
}
230
264
231
265
public static bool ActionKeywordRegistered ( string actionKeyword )
232
266
{
233
267
return actionKeyword != Query . GlobalPluginWildcardSign
234
- && NonGlobalPlugins . ContainsKey ( actionKeyword ) ;
268
+ && NonGlobalPlugins . ContainsKey ( actionKeyword ) ;
235
269
}
236
270
237
271
/// <summary>
@@ -249,6 +283,7 @@ public static void AddActionKeyword(string id, string newActionKeyword)
249
283
{
250
284
NonGlobalPlugins [ newActionKeyword ] = plugin ;
251
285
}
286
+
252
287
plugin . Metadata . ActionKeywords . Add ( newActionKeyword ) ;
253
288
}
254
289
@@ -262,16 +297,16 @@ public static void RemoveActionKeyword(string id, string oldActionkeyword)
262
297
if ( oldActionkeyword == Query . GlobalPluginWildcardSign
263
298
&& // Plugins may have multiple ActionKeywords that are global, eg. WebSearch
264
299
plugin . Metadata . ActionKeywords
265
- . Where ( x => x == Query . GlobalPluginWildcardSign )
266
- . ToList ( )
267
- . Count == 1 )
300
+ . Where ( x => x == Query . GlobalPluginWildcardSign )
301
+ . ToList ( )
302
+ . Count == 1 )
268
303
{
269
304
GlobalPlugins . Remove ( plugin ) ;
270
305
}
271
-
306
+
272
307
if ( oldActionkeyword != Query . GlobalPluginWildcardSign )
273
308
NonGlobalPlugins . Remove ( oldActionkeyword ) ;
274
-
309
+
275
310
276
311
plugin . Metadata . ActionKeywords . Remove ( oldActionkeyword ) ;
277
312
}
0 commit comments