128 lines
3.4 KiB
JavaScript
128 lines
3.4 KiB
JavaScript
// named-pipe-client.js
|
||
const net = require('net');
|
||
const LockClient = require('./lock-client');
|
||
const { v4: uuidv4 } = require('uuid');
|
||
|
||
/**
|
||
* 基于命名管道的读写锁客户端
|
||
* 提供对NamedPipeLockServer的客户端接口,允许应用程序请求和释放读写锁
|
||
* 支持自动重连和超时机制
|
||
*/
|
||
class NamedPipeRWLock extends LockClient {
|
||
/**
|
||
* 创建NamedPipeRWLock实例
|
||
* @param {string} resource - 要锁定的资源名称
|
||
* @param {string} pipePath - 服务器命名管道路径
|
||
* @param {Object} options - 配置选项
|
||
* @param {number} options.timeout - 锁请求超时时间(毫秒),默认30000
|
||
* @param {number} options.retryInterval - 重连间隔(毫秒),默认1000
|
||
* @param {number} options.maxRetries - 最大重连次数,默认5
|
||
*/
|
||
constructor(resource, options = {}) {
|
||
super(resource, options);
|
||
this.resource = resource;
|
||
this.pipePath = options.connect.pipePath;
|
||
}
|
||
|
||
_createConnection(){
|
||
this.socket = net.createConnection(this.pipePath)
|
||
}
|
||
/**
|
||
* 连接到锁服务器
|
||
* @returns {Promise<void>} 连接成功时resolve
|
||
*/
|
||
connect() {
|
||
return new Promise((resolve, reject) => {
|
||
if (this.socket && !this.socket.destroyed) {
|
||
resolve();
|
||
return;
|
||
}
|
||
|
||
// this.socket = net.createConnection(this.pipePath, () => {
|
||
// console.log(`Connected to lock server at ${this.pipePath}`);
|
||
// this.retryCount = 0;
|
||
// resolve();
|
||
// });
|
||
this._createConnection()
|
||
this.socket.on('connect', () => {
|
||
this._logger.debug(`Connected to lock server at ${this.pipePath}`);
|
||
this.retryCount = 0;
|
||
resolve();
|
||
});
|
||
|
||
this.socket.on('error', (error) => {
|
||
this._logger.error('Connection error:', error);
|
||
reject(error);
|
||
});
|
||
|
||
this.socket.on('data', data => this.handleMessage(data));
|
||
this.socket.on('close', () => this.handleDisconnect());
|
||
this.socket.on('end', () => this.handleDisconnect());
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 处理从服务器收到的消息
|
||
* @param {Buffer} data - 接收的数据
|
||
*/
|
||
handleMessage(data) {
|
||
try {
|
||
const messages = data.toString().split('\n').filter(msg => msg.trim());
|
||
|
||
for (const msg of messages) {
|
||
const message = JSON.parse(msg);
|
||
|
||
switch (message.type) {
|
||
case 'lockGranted':
|
||
this.emit('lockGranted', message);
|
||
break;
|
||
case 'error':
|
||
this.emit('error', message);
|
||
break;
|
||
default:
|
||
console.warn('Unknown message type:', message.type);
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error('Error parsing message:', error, 'Raw data:', data.toString());
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* 向服务器发送消息
|
||
* @param {Object} message - 要发送的消息对象
|
||
*/
|
||
sendMessage(message) {
|
||
if (this.socket && !this.socket.destroyed) {
|
||
try {
|
||
this.socket.write(JSON.stringify(message) + '\n');
|
||
} catch (error) {
|
||
console.error('Error sending message:', error);
|
||
this.handleDisconnect();
|
||
}
|
||
} else {
|
||
console.error('Socket not connected');
|
||
this.handleDisconnect();
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/**
|
||
* 关闭连接
|
||
*/
|
||
close() {
|
||
if (this.socket) {
|
||
this.socket.removeAllListeners();
|
||
|
||
this.socket.end();
|
||
this.socket.destroy();
|
||
}
|
||
this.cleanup();
|
||
}
|
||
}
|
||
|
||
module.exports = NamedPipeRWLock; |