node-firebird 1.1.10 → 2.0.0

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.
@@ -1,98 +1,133 @@
1
1
  const Events = require('events');
2
2
  const { doError } = require('../callback');
3
3
 
4
+ class FbEventManager extends Events.EventEmitter {
5
+ constructor(db, eventconnection, eventid, callback) {
6
+ super();
7
+ this.db = db;
8
+ this.eventconnection = eventconnection;
9
+ this.events = {};
10
+ this.eventid = eventid;
11
+ this._createEventLoop(callback);
12
+ }
4
13
 
5
- function FbEventManager(db, eventconnection, eventid, callback) {
6
- this.db = db;
7
- this.eventconnection = eventconnection;
8
- this.events = {};
9
- this.eventid = eventid;
10
- this._createEventLoop(callback);
11
- }
14
+ _createEventLoop(callback) {
15
+ var self = this;
16
+ var cnx = this.db.connection;
17
+ this.eventconnection.emgr = this;
18
+ console.log('[EventManager] Creating event loop, eventid:', this.eventid);
19
+ // create the loop
20
+ function loop(first) {
21
+ console.log('[EventManager] Calling queEvents, first:', first, 'events:', Object.keys(self.events));
22
+ cnx.queEvents(self.events, self.eventid, function (err, ret) {
23
+ console.log('[EventManager] queEvents callback, err:', err, 'ret:', ret, 'first:', first);
24
+ if (err) {
25
+ console.log('[EventManager] queEvents error:', err);
26
+ doError(err, callback);
27
+ return;
28
+ }
29
+ if (first) {
30
+ console.log('[EventManager] First loop complete, calling callback');
31
+ callback(null);
32
+ }
33
+ })
34
+ }
12
35
 
13
- FbEventManager.prototype.__proto__ = Object.create(Events.EventEmitter.prototype, {
14
- constructor: {
15
- value: FbEventManager,
16
- enumberable: false
17
- }
18
- });
19
-
20
- FbEventManager.prototype._createEventLoop = function (callback) {
21
- var self = this;
22
- var cnx = this.db.connection;
23
- this.eventconnection.emgr = this;
24
- // create the loop
25
- function loop(first) {
26
- cnx.queEvents(self.events, self.eventid, function (err, ret) {
27
- if (err) {
28
- doError(err, callback);
36
+ this.eventconnection.eventcallback = function (err, ret) {
37
+ console.log('[EventManager] eventcallback invoked, err:', err, 'eventid match:', self.eventid === ret?.eventid);
38
+ if (err || (self.eventid !== ret.eventid)) {
39
+ doError(err || new Error('Bad eventid'), callback);
29
40
  return;
30
41
  }
31
- if (first)
32
- callback();
33
- })
34
- }
35
42
 
36
- this.eventconnection.eventcallback = function (err, ret) {
37
- if (err || (self.eventid !== ret.eventid)) {
38
- doError(err || new Error('Bad eventid'), callback);
39
- return;
40
- }
43
+ ret.events.forEach(function (event) {
44
+ self.emit('post_event', event.name, event.count)
45
+ })
41
46
 
42
- ret.events.forEach(function (event) {
43
- self.emit('post_event', event.name, event.count)
44
- })
47
+ loop(false);
48
+ }
45
49
 
46
- loop(false);
50
+ loop(true);
47
51
  }
48
52
 
49
- loop(true);
50
- }
53
+ _changeEvent(callback) {
54
+ var self = this;
51
55
 
52
- FbEventManager.prototype._changeEvent = function (callback) {
53
- var self = this;
56
+ console.log('[EventManager] _changeEvent called, eventid:', this.eventid, 'events:', Object.keys(self.events));
57
+ // Temporarily suppress the event loop to prevent stale op_event
58
+ // notifications from pushing spurious queEvents onto the main
59
+ // connection queue while closeEvents + queEvents are in flight
60
+ var savedCallback = self.eventconnection.eventcallback;
61
+ self.eventconnection.eventcallback = null;
62
+ console.log('[EventManager] Suppressed event callback, calling closeEvents');
54
63
 
55
- self.db.connection.closeEvents(this.eventid, function (err) {
56
- if (err) {
57
- doError(err, callback);
58
- return;
59
- }
60
-
61
- self.db.connection.queEvents(self.events, self.eventid, callback);
62
- })
63
- }
64
+ self.db.connection.closeEvents(this.eventid, function (err) {
65
+ console.log('[EventManager] closeEvents callback, err:', err);
66
+ if (err) {
67
+ self.eventconnection.eventcallback = savedCallback;
68
+ doError(err, callback);
69
+ return;
70
+ }
71
+
72
+ console.log('[EventManager] closeEvents success, calling queEvents');
73
+ self.db.connection.queEvents(self.events, self.eventid, function (err, ret) {
74
+ console.log('[EventManager] queEvents callback in _changeEvent, err:', err, 'ret:', ret);
75
+ // Restore the event loop now that our queEvents is safely queued
76
+ self.eventconnection.eventcallback = savedCallback;
77
+ console.log('[EventManager] Restored event callback');
78
+ if (err) {
79
+ console.log('[EventManager] queEvents error in _changeEvent:', err);
80
+ doError(err, callback);
81
+ return;
82
+ }
83
+ console.log('[EventManager] _changeEvent complete, calling final callback');
84
+ callback(null, ret);
85
+ });
86
+ })
87
+ }
64
88
 
65
- FbEventManager.prototype.registerEvent = function (events, callback) {
66
- var self = this;
89
+ registerEvent(events, callback) {
90
+ var self = this;
67
91
 
68
- if (self.db.connection._isClosed || self.eventconnection._isClosed)
69
- return self.eventconnection.throwClosed(callback);
92
+ console.log('[EventManager] registerEvent called with events:', events);
93
+ console.log('[EventManager] Connection closed?', self.db.connection._isClosed, 'Event connection closed?', self.eventconnection._isClosed);
94
+
95
+ if (self.db.connection._isClosed || self.eventconnection._isClosed)
96
+ return self.eventconnection.throwClosed(callback);
70
97
 
71
- events.forEach((event) => self.events[event] = self.events[event] || 0);
72
- self._changeEvent(callback);
73
- }
98
+ events.forEach((event) => self.events[event] = self.events[event] || 0);
99
+ console.log('[EventManager] Events registered, current events:', Object.keys(self.events));
100
+ self._changeEvent(callback);
101
+ }
74
102
 
75
- FbEventManager.prototype.unregisterEvent = function (events, callback) {
76
- var self = this;
103
+ unregisterEvent(events, callback) {
104
+ var self = this;
77
105
 
78
- if (self.db.connection._isClosed || self.eventconnection._isClosed)
79
- return self.eventconnection.throwClosed(callback);
106
+ if (self.db.connection._isClosed || self.eventconnection._isClosed)
107
+ return self.eventconnection.throwClosed(callback);
80
108
 
81
- events.forEach(function (event) { delete self.events[event] });
82
- self._changeEvent(callback);
83
- }
109
+ events.forEach(function (event) { delete self.events[event] });
110
+ self._changeEvent(callback);
111
+ }
84
112
 
85
- FbEventManager.prototype.close = function (callback) {
86
- var self = this;
113
+ close(callback) {
114
+ var self = this;
87
115
 
88
- self.db.connection.closeEvents(this.eventid, function (err) {
89
- if (err) {
90
- doError(err, callback);
91
- return;
92
- }
116
+ // Prevent the event loop from re-queuing on stale op_event notifications
117
+ // that may arrive between closeEvents and socket.end()
118
+ self.eventconnection.eventcallback = null;
119
+
120
+ self.db.connection.closeEvents(this.eventid, function (err) {
121
+ if (err) {
122
+ doError(err, callback);
123
+ return;
124
+ }
93
125
 
94
- self.eventconnection._socket.end();
95
- });
126
+ self.eventconnection._socket.end();
127
+ if (callback)
128
+ callback();
129
+ });
130
+ }
96
131
  }
97
132
 
98
133
  module.exports = FbEventManager;