Skip to content

Commit b6e156c

Browse files
committed
(GH-136) Add loading information to the Puppet Version command
Previously the Language client had no way to know whether the langauge server had completed loading of facts, types and functions. This caused requests to be blocked because of mutex locks while this information is being loaded. This commit; - Adds three properties which the client can use to determine the loading status of various parts of the Language Server, with unit tests - The puppet and facter helpers were modified to expose a *_loaded? method - The puppet and facter helpers will now return empty datasets if they in the process of being loaded on another thread. This speeds up responses to the client
1 parent 98dbaaf commit b6e156c

File tree

6 files changed

+65
-6
lines changed

6 files changed

+65
-6
lines changed

client/src/messages.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ export interface PuppetVersionDetails {
88
puppetVersion: string;
99
facterVersion: string;
1010
languageServerVersion: string;
11+
factsLoaded: boolean;
12+
functionsLoaded: boolean;
13+
typesLoaded: boolean;
1114
}
1215

1316
export interface PuppetResourceRequestParams {

server/lib/languageserver/puppet_version.rb

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
module LanguageServer
22
module PuppetVersion
33
# export interface PuppetVersionDetails {
4-
# puppetVersion: string;
5-
# facterVersion: string;
6-
# languageServerVersion: string;
4+
# puppetVersion: string;
5+
# facterVersion: string;
6+
# languageServerVersion: string;
7+
# factsLoaded: boolean;
8+
# functionsLoaded: boolean;
9+
# typesLoaded: boolean;
710
# }
811

912
def self.create(options)
@@ -13,6 +16,11 @@ def self.create(options)
1316

1417
result['puppetVersion'] = options['puppetVersion']
1518
result['facterVersion'] = options['facterVersion']
19+
20+
result['factsLoaded'] = options['factsLoaded'] unless options['factsLoaded'].nil?
21+
result['functionsLoaded'] = options['functionsLoaded'] unless options['functionsLoaded'].nil?
22+
result['typesLoaded'] = options['typesLoaded'] unless options['typesLoaded'].nil?
23+
1624
result['languageServerVersion'] = PuppetLanguageServer.version
1725

1826
result

server/lib/puppet-languageserver/facter_helper.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module PuppetLanguageServer
22
module FacterHelper
33
@ops_lock = Mutex.new
4+
@facts_loaded = nil
45

56
def self.reset
67
@ops_lock.synchronize do
@@ -14,13 +15,18 @@ def self.load_facts_async
1415
end
1516
end
1617

18+
def self.facts_loaded?
19+
@facts_loaded.nil? ? false : @facts_loaded
20+
end
21+
1722
def self.load_facts
1823
@ops_lock.synchronize do
1924
_load_facts
2025
end
2126
end
2227

2328
def self.facts
29+
return {} if @facts_loaded == false
2430
@ops_lock.synchronize do
2531
_load_facts if @fact_hash.nil?
2632
@fact_hash.clone
@@ -30,6 +36,7 @@ def self.facts
3036
# DO NOT ops_lock on any of these methods
3137
# deadlocks will ensue!
3238
def self._reset
39+
@facts_loaded = nil
3340
Facter.reset
3441
@fact_hash = nil
3542
end
@@ -40,6 +47,7 @@ def self._load_facts
4047
Facter.loadfacts
4148
@fact_hash = Facter.to_hash
4249
PuppetLanguageServer.log_message(:debug, "[FacterHelper::_load_facts] Finished loading #{@fact_hash.keys.count} facts")
50+
@facts_loaded = true
4351
end
4452
private_class_method :_load_facts
4553
end

server/lib/puppet-languageserver/message_router.rb

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,12 @@ def receive_request(request)
4343
request.reply_result(nil)
4444

4545
when 'puppet/getVersion'
46-
request.reply_result(LanguageServer::PuppetVersion.create('puppetVersion' => Puppet.version,
47-
'facterVersion' => Facter.version))
46+
request.reply_result(LanguageServer::PuppetVersion.create('puppetVersion' => Puppet.version,
47+
'facterVersion' => Facter.version,
48+
'factsLoaded' => PuppetLanguageServer::FacterHelper.facts_loaded?,
49+
'functionsLoaded' => PuppetLanguageServer::PuppetHelper.functions_loaded?,
50+
'typesLoaded' => PuppetLanguageServer::PuppetHelper.types_loaded?
51+
))
4852

4953
when 'puppet/getResource'
5054
type_name = request.params['typename']

server/lib/puppet-languageserver/puppet_helper.rb

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ module PuppetHelper
88
@ops_lock_funcs = Mutex.new
99
@types_hash = nil
1010
@function_module = nil
11-
11+
@types_loaded = nil
12+
@functions_loaded = nil
13+
1214
def self.reset
1315
@ops_lock_types.synchronize do
1416
@ops_lock_funcs.synchronize do
@@ -35,6 +37,10 @@ def self.load_types_async
3537
end
3638
end
3739

40+
def self.types_loaded?
41+
@types_loaded.nil? ? false : @types_loaded
42+
end
43+
3844
def self.load_types
3945
@ops_lock_types.synchronize do
4046
_load_types
@@ -43,6 +49,7 @@ def self.load_types
4349

4450
def self.get_type(name)
4551
result = nil
52+
return result if @types_loaded == false
4653
@ops_lock_types.synchronize do
4754
_load_types if @types_hash.nil?
4855
result = @types_hash[name.intern]
@@ -52,6 +59,7 @@ def self.get_type(name)
5259

5360
def self.type_names
5461
result = []
62+
return result if @types_loaded == false
5563
@ops_lock_types.synchronize do
5664
_load_types if @types_hash.nil?
5765
result = @types_hash.keys.map(&:to_s)
@@ -60,6 +68,10 @@ def self.type_names
6068
end
6169

6270
# Functions
71+
def self.functions_loaded?
72+
@functions_loaded.nil? ? false : @functions_loaded
73+
end
74+
6375
def self.load_functions
6476
@ops_lock_funcs.synchronize do
6577
_load_functions if @function_module.nil?
@@ -74,6 +86,7 @@ def self.load_functions_async
7486

7587
def self.functions
7688
result = []
89+
return result if @functions_loaded == false
7790
@ops_lock_funcs.synchronize do
7891
_load_functions if @function_module.nil?
7992
result = @function_module.all_function_info.dup
@@ -83,6 +96,7 @@ def self.functions
8396

8497
def self.function(name)
8598
result = nil
99+
return result if @functions_loaded == false
86100
@ops_lock_funcs.synchronize do
87101
_load_functions if @function_module.nil?
88102
result = @function_module.all_function_info[name.intern]
@@ -92,6 +106,7 @@ def self.function(name)
92106

93107
def self.function_names
94108
result = []
109+
return result if @functions_loaded == false
95110
@ops_lock_funcs.synchronize do
96111
_load_functions if @function_module.nil?
97112
result = @function_module.all_function_info.keys.map(&:to_s)
@@ -104,6 +119,8 @@ def self.function_names
104119
def self._reset
105120
@types_hash = nil
106121
@function_module = nil
122+
@types_loaded = nil
123+
@functions_loaded = nil
107124
end
108125
private_class_method :_reset
109126

@@ -118,6 +135,7 @@ def self.prune_resource_parameters(resources)
118135
private_class_method :prune_resource_parameters
119136

120137
def self._load_types
138+
@types_loaded = false
121139
@types_hash = {}
122140
# This is an expensive call
123141
# From https://github.com/puppetlabs/puppet/blob/ebd96213cab43bb2a8071b7ac0206c3ed0be8e58/lib/puppet/metatype/manager.rb#L182-L189
@@ -143,11 +161,13 @@ def self._load_types
143161
type_count = @types_hash.count
144162
PuppetLanguageServer.log_message(:debug, "[PuppetHelper::_load_types] Finished loading #{type_count} types")
145163

164+
@types_loaded = true
146165
nil
147166
end
148167
private_class_method :_load_types
149168

150169
def self._load_functions
170+
@functions_loaded = false
151171
autoloader = Puppet::Parser::Functions.autoloader
152172

153173
# This is an expensive call
@@ -165,6 +185,7 @@ def self._load_functions
165185

166186
function_count = @function_module.all_function_info.keys.map(&:to_s).count
167187
PuppetLanguageServer.log_message(:debug, "[PuppetHelper::_load_functions] Finished loading #{function_count} functions")
188+
@functions_loaded = true
168189
nil
169190
end
170191
private_class_method :_load_functions

server/spec/unit/puppet-languageserver/message_router_spec.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,21 @@
5757
it 'should reply with the Language Server version' do
5858
expect(request).to receive(:reply_result).with(hash_including('languageServerVersion'))
5959

60+
subject.receive_request(request)
61+
end
62+
it 'should reply with whether the facts are loaded' do
63+
expect(request).to receive(:reply_result).with(hash_including('factsLoaded'))
64+
65+
subject.receive_request(request)
66+
end
67+
it 'should reply with whether the functions are loaded' do
68+
expect(request).to receive(:reply_result).with(hash_including('functionsLoaded'))
69+
70+
subject.receive_request(request)
71+
end
72+
it 'should reply with whether the types are loaded' do
73+
expect(request).to receive(:reply_result).with(hash_including('typesLoaded'))
74+
6075
subject.receive_request(request)
6176
end
6277
end

0 commit comments

Comments
 (0)