omgebouwd naar adonisjs, werkt nog niet echt goed
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
import nntpConfig from '#config/nntp'
|
||||
import { NNTP } from "nntp-js";
|
||||
|
||||
class NntpService {
|
||||
private readonly poolSize: number;
|
||||
private allConnections: Set<any>;
|
||||
private idleConnections: any[];
|
||||
private waiters: ((conn: any) => void)[];
|
||||
private createdCount: number;
|
||||
|
||||
constructor(poolSize = 10) {
|
||||
this.poolSize = poolSize;
|
||||
this.allConnections = new Set();
|
||||
this.idleConnections = [];
|
||||
this.waiters = [];
|
||||
this.createdCount = 0;
|
||||
console.log(`NNTP Pool initialized with size ${this.poolSize}`)
|
||||
}
|
||||
|
||||
private async _createConnection() {
|
||||
// This connection logic is based on the older, working pool implementation.
|
||||
const conn = new NNTP(nntpConfig.host, nntpConfig.port);
|
||||
await conn.connect();
|
||||
if (nntpConfig.user) {
|
||||
await conn.login(nntpConfig.user, nntpConfig.password?.release());
|
||||
}
|
||||
this.allConnections.add(conn);
|
||||
return conn;
|
||||
}
|
||||
|
||||
public async acquire() {
|
||||
if (this.idleConnections.length > 0) {
|
||||
console.log('Reusing existing connection from pool.');
|
||||
return this.idleConnections.pop();
|
||||
}
|
||||
|
||||
if (this.createdCount < this.poolSize) {
|
||||
this.createdCount++;
|
||||
console.log(`Creating new connection (${this.createdCount}/${this.poolSize}).`);
|
||||
return this._createConnection();
|
||||
}
|
||||
|
||||
console.log(`Pool maxed out at ${this.poolSize}. Waiting for a connection to become available.`);
|
||||
return new Promise(resolve => this.waiters.push(resolve));
|
||||
}
|
||||
|
||||
public release(conn: any) {
|
||||
if (this.waiters.length > 0) {
|
||||
console.log('Releasing connection directly to a waiting task.');
|
||||
const resolve = this.waiters.shift();
|
||||
if(resolve) resolve(conn);
|
||||
} else {
|
||||
console.log('Returning connection to the idle pool.');
|
||||
this.idleConnections.push(conn);
|
||||
}
|
||||
}
|
||||
|
||||
public async shutdown() {
|
||||
console.log('Shutting down all connections in the pool.');
|
||||
const shutdownPromises: Promise<any>[] = [];
|
||||
for (const conn of this.allConnections) {
|
||||
shutdownPromises.push(conn.quit());
|
||||
}
|
||||
await Promise.all(shutdownPromises);
|
||||
this.allConnections.clear();
|
||||
this.idleConnections.length = 0;
|
||||
this.waiters.length = 0;
|
||||
this.createdCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
export default new NntpService();
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Queue } from 'bullmq'
|
||||
import queueConfig from '#config/queue'
|
||||
|
||||
class QueueService {
|
||||
public readonly nntpFetchQueue: Queue
|
||||
public readonly headerQueue: Queue
|
||||
public readonly fileQueue: Queue
|
||||
public readonly bodyQueue: Queue
|
||||
public readonly collectionQueue: Queue
|
||||
|
||||
constructor() {
|
||||
this.nntpFetchQueue = new Queue('nntp-fetch-queue', { connection: queueConfig.connection })
|
||||
this.headerQueue = new Queue('header-queue', { connection: queueConfig.connection })
|
||||
this.fileQueue = new Queue('file-queue', { connection: queueConfig.connection })
|
||||
this.bodyQueue = new Queue('body-queue', { connection: queueConfig.connection })
|
||||
this.collectionQueue = new Queue('collection-queue', { connection: queueConfig.connection })
|
||||
}
|
||||
|
||||
async closeAll() {
|
||||
await Promise.all([
|
||||
this.nntpFetchQueue.close(),
|
||||
this.headerQueue.close(),
|
||||
this.fileQueue.close(),
|
||||
this.bodyQueue.close(),
|
||||
this.collectionQueue.close(),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
export default new QueueService()
|
||||
@@ -0,0 +1,15 @@
|
||||
import { createRequire } from 'module'
|
||||
import redisConfig from '#config/redis'
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
const IORedis = require('ioredis')
|
||||
|
||||
class RedisService {
|
||||
public readonly client: any
|
||||
|
||||
constructor() {
|
||||
this.client = new IORedis(redisConfig.connections.main)
|
||||
}
|
||||
}
|
||||
|
||||
export default new RedisService()
|
||||
@@ -0,0 +1,19 @@
|
||||
import { decode } from 'simple-yenc'
|
||||
|
||||
export class YencFile {
|
||||
private buffer: Buffer | null = null
|
||||
|
||||
public processPart(partBuffer: Buffer) {
|
||||
// This is a simplified implementation.
|
||||
// simple-yenc's decode function is synchronous and works on a full buffer.
|
||||
// A more complex implementation would handle multi-part decoding.
|
||||
this.buffer = decode(partBuffer)
|
||||
}
|
||||
|
||||
public getBuffer(): Buffer {
|
||||
if (!this.buffer) {
|
||||
throw new Error('No data has been processed yet.')
|
||||
}
|
||||
return this.buffer
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
export function parseYencMeta(buffer: Buffer): { header: Record<string, any>; crc32?: string } {
|
||||
const text = buffer.toString('latin1')
|
||||
const lines = text.split(/\\r?\\n/)
|
||||
|
||||
const header: Record<string, any> = {}
|
||||
let crc32: string | undefined
|
||||
|
||||
for (const line of lines) {
|
||||
if (line.startsWith('=ybegin')) {
|
||||
const parts = line.split(' ')
|
||||
parts.forEach((part) => {
|
||||
if (part.includes('=')) {
|
||||
const [key, value] = part.split('=')
|
||||
if (key === 'name') {
|
||||
header[key] = value.trim()
|
||||
} else {
|
||||
header[key] = parseInt(value, 10)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else if (line.startsWith('=ypart')) {
|
||||
const match = /begin=(\d+)/.exec(line)
|
||||
if (match) {
|
||||
header.partBegin = parseInt(match[1], 10)
|
||||
}
|
||||
} else if (line.startsWith('=yend')) {
|
||||
const match = /crc32=([a-fA-F0-9]+)/.exec(line)
|
||||
if (match) {
|
||||
crc32 = match[1]
|
||||
}
|
||||
break // End of yenc data
|
||||
}
|
||||
}
|
||||
|
||||
return { header, crc32 }
|
||||
}
|
||||
Reference in New Issue
Block a user