nlocks/lock-client.namedpipe.js

128 lines
3.4 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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;