debounced 0.1.16 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/debounced/javascript/server.mjs +2 -1
- data/lib/debounced/javascript/service.mjs +140 -0
- data/lib/debounced/service_proxy.rb +50 -57
- data/lib/debounced/version.rb +1 -1
- data/lib/debounced.rb +8 -4
- metadata +22 -37
- data/lib/debounced/javascript/debounce.mjs +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: beb111cd5043d97b903d9e89278437564f65fd5794f4531d6e5c6e57dca79859
|
4
|
+
data.tar.gz: b872450de202d28e51d32eac774b27238a328972a7b3363c0ca77d5b137897f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f70040e9197b72f7e8b91b6bae9d736a3f840c6da34817722949f23a4d82c6b798a9a0011345ca623ba7bd4fc2bab48fa498d41cebf70dd59a9d7459d277416d
|
7
|
+
data.tar.gz: af31341ddf36fa276c5ad79db3cecdf975795bd1ac130005f18b9cbbab880b157645aa7e2d5c63199a98b999eae1b85e9daee061a2717162c27567d1d11c2564
|
@@ -1,8 +1,9 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
|
3
|
-
import DebounceEventService from './
|
3
|
+
import DebounceEventService from './service.mjs'
|
4
4
|
let socketDescriptor = '/tmp/app.debounceEvents';
|
5
5
|
if (process.argv.length > 2) {
|
6
6
|
socketDescriptor = process.argv[2];
|
7
7
|
}
|
8
|
+
|
8
9
|
new DebounceEventService(socketDescriptor).listen();
|
@@ -0,0 +1,140 @@
|
|
1
|
+
import net from 'net';
|
2
|
+
import fs from 'fs';
|
3
|
+
|
4
|
+
export default class DebounceService {
|
5
|
+
constructor(socketDescriptor) {
|
6
|
+
this._socketDescriptor = socketDescriptor;
|
7
|
+
this._timers = {};
|
8
|
+
this._client = null;
|
9
|
+
this.publishEvent = this.publishEvent.bind(this);
|
10
|
+
this.debounceEvent = this.debounceEvent.bind(this);
|
11
|
+
this.reset = this.reset.bind(this);
|
12
|
+
this.listen = this.listen.bind(this);
|
13
|
+
this.handleError = this.handleError.bind(this);
|
14
|
+
this.onClientConnected = this.onClientConnected.bind(this);
|
15
|
+
this.onClientDisconnected = this.onClientDisconnected.bind(this);
|
16
|
+
this.onConnectionError = this.onConnectionError.bind(this);
|
17
|
+
this.handleMessage = this.handleMessage.bind(this);
|
18
|
+
this.configureServer();
|
19
|
+
}
|
20
|
+
|
21
|
+
onConnectionError(err) {
|
22
|
+
console.log('DebounceService client connection error');
|
23
|
+
this._client = null
|
24
|
+
this.handleError(err);
|
25
|
+
}
|
26
|
+
|
27
|
+
onClientDisconnected() {
|
28
|
+
console.log('DebounceService client disconnected');
|
29
|
+
this._client = null
|
30
|
+
}
|
31
|
+
|
32
|
+
handleMessage(message) {
|
33
|
+
try {
|
34
|
+
const object = JSON.parse(message);
|
35
|
+
if (object.type === 'debounceEvent') {
|
36
|
+
this.debounceEvent(object.data);
|
37
|
+
} else if (object.type === 'reset') {
|
38
|
+
this.reset();
|
39
|
+
} else {
|
40
|
+
console.log('DebounceService unknown message', message);
|
41
|
+
}
|
42
|
+
} catch (e) {
|
43
|
+
console.log('unable to parse message', e);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
onClientConnected(socket) {
|
48
|
+
if (this._client) {
|
49
|
+
console.log('DebounceService rejecting connection: already has a client');
|
50
|
+
socket.end();
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
|
54
|
+
console.log('DebounceService client connected');
|
55
|
+
let connectionBuffer = '';
|
56
|
+
this._client = socket;
|
57
|
+
socket.on('end', this.onClientDisconnected)
|
58
|
+
socket.on('error', this.onConnectionError)
|
59
|
+
socket.on('data', data => {
|
60
|
+
console.log('DebounceService data received', data.toString());
|
61
|
+
connectionBuffer += data.toString();
|
62
|
+
const messages = connectionBuffer.split('\f');
|
63
|
+
connectionBuffer = ''
|
64
|
+
if (!connectionBuffer.endsWith('\f')) {
|
65
|
+
connectionBuffer = messages.pop();
|
66
|
+
}
|
67
|
+
messages.forEach(this.handleMessage);
|
68
|
+
})
|
69
|
+
}
|
70
|
+
|
71
|
+
configureServer() {
|
72
|
+
this.server = net.createServer(this.onClientConnected)
|
73
|
+
this.server.on('error', this.handleError);
|
74
|
+
}
|
75
|
+
|
76
|
+
listen() {
|
77
|
+
// Remove the existing socket file if it exists
|
78
|
+
if (fs.existsSync(this._socketDescriptor)) {
|
79
|
+
console.log('DebounceEventService removing stale socket file ', this._socketDescriptor);
|
80
|
+
fs.unlinkSync(this._socketDescriptor);
|
81
|
+
}
|
82
|
+
|
83
|
+
process.on('exit', (code) => {
|
84
|
+
console.log(`Process exiting with code: ${code}`);
|
85
|
+
this.server.close();
|
86
|
+
});
|
87
|
+
|
88
|
+
process.on('SIGTERM', () => {
|
89
|
+
console.log('Process received SIGTERM');
|
90
|
+
this.server.close();
|
91
|
+
process.exit(0);
|
92
|
+
});
|
93
|
+
|
94
|
+
process.on('SIGINT', () => {
|
95
|
+
console.log('Process received SIGINT');
|
96
|
+
this.server.close();
|
97
|
+
process.exit(0);
|
98
|
+
});
|
99
|
+
|
100
|
+
this.server.listen(this._socketDescriptor, () => {
|
101
|
+
console.log('DebounceService listening on', this._socketDescriptor);
|
102
|
+
});
|
103
|
+
}
|
104
|
+
|
105
|
+
publishEvent(descriptor, data) {
|
106
|
+
console.log(`Debounce period expired for ${descriptor}, publishing ${data.klass} event`);
|
107
|
+
const message = JSON.stringify({
|
108
|
+
type: 'publishEvent',
|
109
|
+
data: data
|
110
|
+
});
|
111
|
+
|
112
|
+
try {
|
113
|
+
this._client.write(message);
|
114
|
+
this._client.write("\f");
|
115
|
+
} catch (err) {
|
116
|
+
this.handleError(err);
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
debounceEvent({ descriptor, attributes, klass, timeout }) {
|
121
|
+
if (this._timers[descriptor]) {
|
122
|
+
clearTimeout(this._timers[descriptor]);
|
123
|
+
}
|
124
|
+
|
125
|
+
console.log("Debouncing", descriptor);
|
126
|
+
this._timers[descriptor] = setTimeout(() => {
|
127
|
+
delete this._timers[descriptor];
|
128
|
+
this.publishEvent(descriptor, { attributes, klass });
|
129
|
+
}, timeout * 1000);
|
130
|
+
}
|
131
|
+
|
132
|
+
reset() {
|
133
|
+
Object.values(this._timers).forEach(timerID => clearTimeout(timerID));
|
134
|
+
this._timers = {};
|
135
|
+
}
|
136
|
+
|
137
|
+
handleError(err) {
|
138
|
+
console.log('\n\n######\nERROR: ', err);
|
139
|
+
}
|
140
|
+
}
|
@@ -1,7 +1,14 @@
|
|
1
1
|
require 'socket'
|
2
|
-
require '
|
2
|
+
require 'json'
|
3
|
+
require 'json/add/core'
|
4
|
+
require 'debug'
|
3
5
|
|
4
6
|
module Debounced
|
7
|
+
###
|
8
|
+
# Ruby interface to the debounce service
|
9
|
+
# Input is an activity descriptor, and an object.
|
10
|
+
# When the activity is debounced, a callback method is invoked on the object.
|
11
|
+
# Assumes the object class has an initializer that accepts a hash of attributes, which are the instance variables
|
5
12
|
class ServiceProxy
|
6
13
|
DELIMITER = "\f".freeze
|
7
14
|
|
@@ -11,16 +18,12 @@ module Debounced
|
|
11
18
|
|
12
19
|
def listen(abort_signal = nil)
|
13
20
|
Thread.new do
|
14
|
-
|
15
|
-
Rails.application.executor.wrap do
|
16
|
-
receive(abort_signal)
|
17
|
-
end
|
18
|
-
else
|
19
|
-
receive(abort_signal)
|
20
|
-
end
|
21
|
+
receive(abort_signal)
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
25
|
+
###
|
26
|
+
# Send message to server to reset its state. Useful for automated testing.
|
24
27
|
def reset
|
25
28
|
if socket.nil?
|
26
29
|
log_debug("No connection to #{server_name}; unable to reset server.")
|
@@ -30,13 +33,13 @@ module Debounced
|
|
30
33
|
end
|
31
34
|
end
|
32
35
|
|
33
|
-
def
|
36
|
+
def debounce_activity(activity_descriptor, object, timeout)
|
34
37
|
if socket.nil?
|
35
|
-
log_debug("No connection to #{server_name};
|
36
|
-
|
38
|
+
log_debug("No connection to #{server_name}; skipping debounce step.")
|
39
|
+
trigger_callback(object)
|
37
40
|
else
|
38
41
|
log_debug("Sending #{object.inspect} to #{server_name}")
|
39
|
-
transmit(
|
42
|
+
transmit(build_request(activity_descriptor, object, timeout))
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
@@ -47,25 +50,27 @@ module Debounced
|
|
47
50
|
break if abort_signal&.set?
|
48
51
|
|
49
52
|
if socket.nil?
|
50
|
-
log_debug("Waiting for #{server_name}...")
|
53
|
+
log_debug("Waiting for #{server_name} to start...")
|
51
54
|
sleep(@wait_timeout)
|
52
55
|
next
|
53
56
|
end
|
54
57
|
|
58
|
+
log_debug("Waiting for data from #{server_name}...")
|
55
59
|
message = socket.gets(DELIMITER, chomp: true)
|
56
|
-
|
57
|
-
# gets => nil when server crashed.... try to reconnect
|
58
60
|
if message.nil?
|
61
|
+
log_info("Server #{server_name} ended connection")
|
59
62
|
close
|
60
|
-
|
63
|
+
break
|
61
64
|
end
|
62
65
|
|
66
|
+
log_debug("Received #{message}")
|
63
67
|
payload = deserialize_payload(message)
|
68
|
+
log_debug("Parsed #{payload}")
|
64
69
|
next unless payload['type'] == 'publishEvent'
|
65
70
|
|
66
|
-
|
71
|
+
trigger_callback(instantiate_debounced_object(payload['data']))
|
67
72
|
rescue IO::TimeoutError
|
68
|
-
# Ignored
|
73
|
+
# Ignored - normal flow of loop: check abort_signal (L48), get data (L56), timeout waiting for data (69)
|
69
74
|
end
|
70
75
|
rescue StandardError => e
|
71
76
|
log_warn("Unable to listen for messages from #{server_name}: #{e.message}")
|
@@ -81,24 +86,24 @@ module Debounced
|
|
81
86
|
@socket = nil
|
82
87
|
end
|
83
88
|
|
84
|
-
def
|
89
|
+
def build_request(descriptor, object, timeout)
|
85
90
|
{
|
86
91
|
type: 'debounceEvent',
|
87
92
|
data: {
|
88
|
-
timeout
|
89
|
-
descriptor
|
90
|
-
klass:
|
91
|
-
attributes:
|
93
|
+
timeout:,
|
94
|
+
descriptor:,
|
95
|
+
klass: object.class.name,
|
96
|
+
attributes: extract_attributes(object)
|
92
97
|
}
|
93
98
|
}
|
94
99
|
end
|
95
100
|
|
96
|
-
def
|
97
|
-
if
|
98
|
-
|
101
|
+
def extract_attributes(object)
|
102
|
+
if object.respond_to?(:attributes)
|
103
|
+
object.attributes
|
99
104
|
else
|
100
|
-
|
101
|
-
hash[var.to_s.delete('@')] =
|
105
|
+
object.instance_variables.each_with_object({}) do |var, hash|
|
106
|
+
hash[var.to_s.delete('@')] = object.instance_variable_get(var)
|
102
107
|
end
|
103
108
|
end
|
104
109
|
end
|
@@ -112,21 +117,21 @@ module Debounced
|
|
112
117
|
end
|
113
118
|
|
114
119
|
def serialize_payload(payload)
|
115
|
-
"#{
|
120
|
+
"#{JSON.generate(payload)}#{DELIMITER}" # inject EOM delimiter (form feed character)
|
116
121
|
end
|
117
122
|
|
118
123
|
def deserialize_payload(payload)
|
119
|
-
|
124
|
+
JSON.parse(payload)
|
120
125
|
end
|
121
126
|
|
122
|
-
def
|
123
|
-
object.send(Debounced.configuration.callback_method
|
127
|
+
def trigger_callback(object)
|
128
|
+
object.send(Debounced.configuration.callback_method)
|
124
129
|
end
|
125
130
|
|
126
|
-
def
|
127
|
-
klass = data['klass']
|
128
|
-
data = data['attributes']
|
129
|
-
klass.
|
131
|
+
def instantiate_debounced_object(data)
|
132
|
+
klass = Object.const_get(data['klass'])
|
133
|
+
data = data['attributes'].transform_keys(&:to_sym)
|
134
|
+
klass.new(**data)
|
130
135
|
end
|
131
136
|
|
132
137
|
def socket_descriptor
|
@@ -134,40 +139,28 @@ module Debounced
|
|
134
139
|
end
|
135
140
|
|
136
141
|
def socket
|
137
|
-
@socket ||=
|
138
|
-
|
139
|
-
|
142
|
+
@socket ||= begin
|
143
|
+
log_debug("Connecting to #{server_name} at #{socket_descriptor}")
|
144
|
+
UNIXSocket.new(socket_descriptor).tap { it.timeout = @wait_timeout }
|
140
145
|
end
|
141
|
-
###
|
142
|
-
# Errno::ENOENT is raised if the socket file does not exist.
|
143
|
-
# Errno::ECONNREFUSED is raised if the socket file exists but no process is listening on it.
|
144
146
|
rescue Errno::ECONNREFUSED, Errno::ENOENT
|
147
|
+
###
|
148
|
+
# Errno::ENOENT is raised if the socket file does not exist.
|
149
|
+
# Errno::ECONNREFUSED is raised if the socket file exists but no process is listening on it.
|
145
150
|
log_debug("#{server_name} is not running")
|
146
151
|
nil
|
147
152
|
end
|
148
153
|
|
149
154
|
def log_debug(message)
|
150
|
-
|
151
|
-
Rails.logger.debug { message }
|
152
|
-
else
|
153
|
-
puts "[DEBUG] #{message}" if ENV['DEBUG']
|
154
|
-
end
|
155
|
+
Debounced.configuration.logger.debug { message }
|
155
156
|
end
|
156
157
|
|
157
158
|
def log_info(message)
|
158
|
-
|
159
|
-
Rails.logger.info(message)
|
160
|
-
else
|
161
|
-
puts "[INFO] #{message}"
|
162
|
-
end
|
159
|
+
Debounced.configuration.logger.info(message)
|
163
160
|
end
|
164
161
|
|
165
162
|
def log_warn(message)
|
166
|
-
|
167
|
-
Rails.logger.warn(message)
|
168
|
-
else
|
169
|
-
puts "[WARNING] #{message}"
|
170
|
-
end
|
163
|
+
Debounced.configuration.logger.warn(message)
|
171
164
|
end
|
172
165
|
end
|
173
166
|
end
|
data/lib/debounced/version.rb
CHANGED
data/lib/debounced.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require 'debounced/version'
|
2
|
+
require 'debounced/railtie' if defined?(Rails)
|
3
|
+
require 'debounced/service_proxy'
|
4
|
+
require 'semantic_logger'
|
4
5
|
|
5
6
|
module Debounced
|
6
7
|
class Error < StandardError; end
|
@@ -16,12 +17,15 @@ module Debounced
|
|
16
17
|
end
|
17
18
|
|
18
19
|
class Configuration
|
19
|
-
attr_accessor :socket_descriptor, :wait_timeout, :callback_method
|
20
|
+
attr_accessor :socket_descriptor, :wait_timeout, :callback_method, :logger
|
20
21
|
|
21
22
|
def initialize
|
22
23
|
@socket_descriptor = ENV['DEBOUNCED_SOCKET'] || '/tmp/app.debounceEvents'
|
23
24
|
@wait_timeout = ENV['DEBOUNCED_TIMEOUT']&.to_i || 3
|
24
25
|
@callback_method = :publish
|
26
|
+
SemanticLogger.add_appender(file_name: 'debounced_proxy.log', formatter: :color)
|
27
|
+
SemanticLogger.default_level = ENV.fetch('LOG_LEVEL', 'info')
|
28
|
+
@logger = SemanticLogger['ServiceProxy']
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
metadata
CHANGED
@@ -1,92 +1,77 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: debounced
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gary Passero
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-03-
|
10
|
+
date: 2025-03-21 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
|
-
name:
|
13
|
+
name: json
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
15
15
|
requirements:
|
16
16
|
- - "~>"
|
17
17
|
- !ruby/object:Gem::Version
|
18
|
-
version:
|
19
|
-
- - ">="
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
version: 7.0.0
|
18
|
+
version: 2.10.2
|
22
19
|
type: :runtime
|
23
20
|
prerelease: false
|
24
21
|
version_requirements: !ruby/object:Gem::Requirement
|
25
22
|
requirements:
|
26
23
|
- - "~>"
|
27
24
|
- !ruby/object:Gem::Version
|
28
|
-
version:
|
29
|
-
- - ">="
|
30
|
-
- !ruby/object:Gem::Version
|
31
|
-
version: 7.0.0
|
25
|
+
version: 2.10.2
|
32
26
|
- !ruby/object:Gem::Dependency
|
33
|
-
name:
|
27
|
+
name: semantic_logger
|
34
28
|
requirement: !ruby/object:Gem::Requirement
|
35
29
|
requirements:
|
36
30
|
- - "~>"
|
37
31
|
- !ruby/object:Gem::Version
|
38
|
-
version:
|
39
|
-
type: :
|
32
|
+
version: 4.15.0
|
33
|
+
type: :runtime
|
40
34
|
prerelease: false
|
41
35
|
version_requirements: !ruby/object:Gem::Requirement
|
42
36
|
requirements:
|
43
37
|
- - "~>"
|
44
38
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
39
|
+
version: 4.15.0
|
46
40
|
- !ruby/object:Gem::Dependency
|
47
|
-
name:
|
41
|
+
name: rspec
|
48
42
|
requirement: !ruby/object:Gem::Requirement
|
49
43
|
requirements:
|
50
44
|
- - "~>"
|
51
45
|
- !ruby/object:Gem::Version
|
52
|
-
version: '
|
46
|
+
version: '3.0'
|
53
47
|
type: :development
|
54
48
|
prerelease: false
|
55
49
|
version_requirements: !ruby/object:Gem::Requirement
|
56
50
|
requirements:
|
57
51
|
- - "~>"
|
58
52
|
- !ruby/object:Gem::Version
|
59
|
-
version: '
|
53
|
+
version: '3.0'
|
60
54
|
- !ruby/object:Gem::Dependency
|
61
|
-
name:
|
55
|
+
name: debug
|
62
56
|
requirement: !ruby/object:Gem::Requirement
|
63
57
|
requirements:
|
64
58
|
- - "~>"
|
65
59
|
- !ruby/object:Gem::Version
|
66
|
-
version: '
|
67
|
-
|
68
|
-
prerelease: false
|
69
|
-
version_requirements: !ruby/object:Gem::Requirement
|
70
|
-
requirements:
|
71
|
-
- - "~>"
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
version: '2.12'
|
74
|
-
- !ruby/object:Gem::Dependency
|
75
|
-
name: rubocop-rspec
|
76
|
-
requirement: !ruby/object:Gem::Requirement
|
77
|
-
requirements:
|
78
|
-
- - "~>"
|
60
|
+
version: '1.0'
|
61
|
+
- - ">="
|
79
62
|
- !ruby/object:Gem::Version
|
80
|
-
version:
|
63
|
+
version: 1.0.0
|
81
64
|
type: :development
|
82
65
|
prerelease: false
|
83
66
|
version_requirements: !ruby/object:Gem::Requirement
|
84
67
|
requirements:
|
85
68
|
- - "~>"
|
86
69
|
- !ruby/object:Gem::Version
|
87
|
-
version: '
|
88
|
-
|
89
|
-
|
70
|
+
version: '1.0'
|
71
|
+
- - ">="
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 1.0.0
|
74
|
+
description: Leverage JavaScript micro-event loop to debounce events in Ruby applications
|
90
75
|
email:
|
91
76
|
- gary@flytedesk.com
|
92
77
|
executables: []
|
@@ -97,8 +82,8 @@ files:
|
|
97
82
|
- README.md
|
98
83
|
- lib/debounced.rb
|
99
84
|
- lib/debounced/abort_signal.rb
|
100
|
-
- lib/debounced/javascript/debounce.mjs
|
101
85
|
- lib/debounced/javascript/server.mjs
|
86
|
+
- lib/debounced/javascript/service.mjs
|
102
87
|
- lib/debounced/railtie.rb
|
103
88
|
- lib/debounced/service_proxy.rb
|
104
89
|
- lib/debounced/version.rb
|
@@ -1,68 +0,0 @@
|
|
1
|
-
import ipc from 'node-ipc';
|
2
|
-
import fs from 'fs';
|
3
|
-
|
4
|
-
const logLevel = process.env.LOG_LEVEL || 'info';
|
5
|
-
|
6
|
-
export default class DebounceService {
|
7
|
-
constructor(socketDescriptor) {
|
8
|
-
this._socketDescriptor = socketDescriptor;
|
9
|
-
this._timers = {};
|
10
|
-
this.publishEvent = this.publishEvent.bind(this);
|
11
|
-
this.debounceEvent = this.debounceEvent.bind(this);
|
12
|
-
this.reset = this.reset.bind(this);
|
13
|
-
this.listen = this.listen.bind(this);
|
14
|
-
this.handleError = this.handleError.bind(this);
|
15
|
-
this.configureServer();
|
16
|
-
this.registerMessageTypes();
|
17
|
-
}
|
18
|
-
|
19
|
-
registerMessageTypes() {
|
20
|
-
ipc.server.on('debounceEvent', this.debounceEvent);
|
21
|
-
ipc.server.on('reset', this.reset);
|
22
|
-
ipc.server.on('error', this.handleError);
|
23
|
-
}
|
24
|
-
|
25
|
-
configureServer() {
|
26
|
-
// Remove the existing socket file if it exists
|
27
|
-
if (fs.existsSync(this._socketDescriptor)) {
|
28
|
-
console.log('DebounceEventService removing stale socket file ', this._socketDescriptor);
|
29
|
-
fs.unlinkSync(this._socketDescriptor);
|
30
|
-
}
|
31
|
-
|
32
|
-
ipc.config.delimiter = '\f'; // incoming messages are terminated by a form feed character
|
33
|
-
ipc.config.encoding = 'utf8';
|
34
|
-
ipc.config.silent = (logLevel !== 'debug');
|
35
|
-
|
36
|
-
ipc.serve(this._socketDescriptor);
|
37
|
-
}
|
38
|
-
|
39
|
-
listen() {
|
40
|
-
console.log('DebounceService listening on', this._socketDescriptor);
|
41
|
-
ipc.server.start();
|
42
|
-
}
|
43
|
-
|
44
|
-
publishEvent(descriptor, data) {
|
45
|
-
console.log(`Debounce period expired for ${descriptor}, publishing ${data.klass} event`);
|
46
|
-
ipc.server.broadcast("publishEvent", data);
|
47
|
-
}
|
48
|
-
|
49
|
-
debounceEvent({ descriptor, attributes, klass, timeout }) {
|
50
|
-
if (this._timers[descriptor]) {
|
51
|
-
clearTimeout(this._timers[descriptor]);
|
52
|
-
}
|
53
|
-
|
54
|
-
this._timers[descriptor] = setTimeout(() => {
|
55
|
-
delete this._timers[descriptor];
|
56
|
-
this.publishEvent(descriptor, { attributes, klass });
|
57
|
-
}, timeout * 1000);
|
58
|
-
}
|
59
|
-
|
60
|
-
reset() {
|
61
|
-
Object.values(this._timers).forEach(timerID => clearTimeout(timerID));
|
62
|
-
this._timers = {};
|
63
|
-
}
|
64
|
-
|
65
|
-
handleError(err) {
|
66
|
-
console.log('\n\n######\nERROR: ', err);
|
67
|
-
}
|
68
|
-
}
|