كان كل نبضة موقع (كل 1-3 ثوانٍ لكل سائق متصل) تكلّف استعلاماً + كتابة صف السائق في Postgres — أثقل حمل كان على القاعدة، وأثقل حتى من سيرو. - H1/H2: نبضة الموقع = Redis فقط، بعتبات سيرو (10م / 1.0 سرعة / 5° اتجاه). سائق واقف = EXPIRE واحد: لا كتابة، لا نقطة مسار، ولا بثّ للراكب - H3: لقطة آخر موقع على drivers (heading/speed/loc_status/loc_updated_at) يكتبها الـworker دورياً. لم نُنشئ جدولاً منفصلاً — drivers أصلاً صف واحد لكل سائق - H4: driver_tracks — تتراكم في قائمة Redis ويُدرجها الـworker بعبارة واحدة - H5: فهرسا available/busy — البحث يمسح المتاحين فقط. السائق يصير busy عند القبول ويعود available عند الإنهاء/الإلغاء - H8: المطابقة والاحتيال و«الرحلات المتاحة» تقرأ الموقع الحيّ من Redis. كشف تزوير الوصول خاصةً يجب ألّا يحكم بلقطة دورية الـworker صار حقيقياً (كان setInterval فارغاً): سياق Nest مستقل، تفريغ كل 5s، قفل يمنع تراكب الدورات، وتفريغة أخيرة عند SIGTERM. مؤجَّل من H: H6 (سلوك السائق) و H7 (ساعات العمل) — تحليلات تُبنى من driver_tracks لاحقاً. هجرة: DriverLocations. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
36 lines
1.4 KiB
TypeScript
36 lines
1.4 KiB
TypeScript
import { Module } from '@nestjs/common';
|
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
|
import configuration from './config/configuration';
|
|
import { RedisModule } from './common/redis/redis.module';
|
|
import { LocationsModule } from './modules/locations/locations.module';
|
|
|
|
/**
|
|
* وحدة الـworker — عملية منفصلة (`node dist/worker.js`) لا تخدم HTTP.
|
|
* تحمل ما يحتاجه العمل الدوري فقط: قاعدة + Redis + المواقع.
|
|
*/
|
|
@Module({
|
|
imports: [
|
|
ConfigModule.forRoot({ isGlobal: true, load: [configuration] }),
|
|
TypeOrmModule.forRootAsync({
|
|
inject: [ConfigService],
|
|
useFactory: (cfg: ConfigService) => ({
|
|
type: 'postgres' as const,
|
|
host: cfg.get<string>('db.host'),
|
|
port: cfg.get<number>('db.port'),
|
|
database: cfg.get<string>('db.name'),
|
|
username: cfg.get<string>('db.user'),
|
|
password: cfg.get<string>('db.password'),
|
|
// بركة أصغر من الـAPI: الـworker يكتب دفعات قليلة لا طلبات متزامنة.
|
|
extra: { max: parseInt(process.env.WORKER_DB_POOL_MAX ?? '5', 10) },
|
|
entityPrefix: cfg.get<string>('db.tablePrefix'),
|
|
synchronize: false,
|
|
autoLoadEntities: true,
|
|
}),
|
|
}),
|
|
RedisModule,
|
|
LocationsModule,
|
|
],
|
|
})
|
|
export class WorkerModule {}
|