refactor: move backend boot user discovery into repositories
This commit is contained in:
parent
50defe1890
commit
2b36fca143
@ -18,6 +18,8 @@ import { healthTracker } from './services/healthTracker.js';
|
|||||||
import { observabilityService } from './services/observabilityService.js';
|
import { observabilityService } from './services/observabilityService.js';
|
||||||
import { reconciliationService } from './services/reconciliationService.js';
|
import { reconciliationService } from './services/reconciliationService.js';
|
||||||
import { reconciliationWatchdogAutoResumeService } from './services/reconciliationWatchdogAutoResumeService.js';
|
import { reconciliationWatchdogAutoResumeService } from './services/reconciliationWatchdogAutoResumeService.js';
|
||||||
|
import { listActiveTradeProfiles } from './services/profileRepository.js';
|
||||||
|
import { listActiveTradingUsers } from './services/userRepository.js';
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
logger.info(`Starting ${config.PRODUCT_ID} trading backend...`);
|
logger.info(`Starting ${config.PRODUCT_ID} trading backend...`);
|
||||||
@ -46,7 +48,7 @@ async function main() {
|
|||||||
}
|
}
|
||||||
// --- 0. Load User Configuration (Supabase) ---
|
// --- 0. Load User Configuration (Supabase) ---
|
||||||
logger.info('Fetching active users from Supabase...');
|
logger.info('Fetching active users from Supabase...');
|
||||||
const users = await supabaseService.getActiveUsers();
|
let users = await listActiveTradingUsers(supabaseService);
|
||||||
|
|
||||||
// --- 1. Identify Primary Key (for Data Fetching) ---
|
// --- 1. Identify Primary Key (for Data Fetching) ---
|
||||||
const isPlaceholder = (val: string) => !val || val === 'your_key' || val === 'your_secret';
|
const isPlaceholder = (val: string) => !val || val === 'your_key' || val === 'your_secret';
|
||||||
@ -261,7 +263,7 @@ async function main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- 0. Initialize Signal Subscribers (Users & Profiles) ---
|
// --- 0. Initialize Signal Subscribers (Users & Profiles) ---
|
||||||
const profiles = await supabaseService.getActiveProfiles();
|
const profiles = await listActiveTradeProfiles(supabaseService);
|
||||||
|
|
||||||
if (profiles.length > 0) {
|
if (profiles.length > 0) {
|
||||||
logger.info(`👥 Initializing Execution Managers for ${profiles.length} Trade Profiles...`);
|
logger.info(`👥 Initializing Execution Managers for ${profiles.length} Trade Profiles...`);
|
||||||
@ -393,7 +395,8 @@ async function main() {
|
|||||||
// --- PROFILE HOT-RELOAD: Sync new/updated/deactivated profiles periodically ---
|
// --- PROFILE HOT-RELOAD: Sync new/updated/deactivated profiles periodically ---
|
||||||
setInterval(async () => {
|
setInterval(async () => {
|
||||||
try {
|
try {
|
||||||
const latestProfiles = await supabaseService.getActiveProfiles();
|
users = await listActiveTradingUsers(supabaseService);
|
||||||
|
const latestProfiles = await listActiveTradeProfiles(supabaseService);
|
||||||
const currentIds = new Set(userContexts.map(c => c.profileId));
|
const currentIds = new Set(userContexts.map(c => c.profileId));
|
||||||
const latestIds = new Set(latestProfiles.map((p: any) => p.id));
|
const latestIds = new Set(latestProfiles.map((p: any) => p.id));
|
||||||
|
|
||||||
|
|||||||
52
backend/src/services/userRepository.ts
Normal file
52
backend/src/services/userRepository.ts
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import logger from '../utils/logger.js';
|
||||||
|
import type { UserConfig, supabaseService } from './SupabaseService.js';
|
||||||
|
|
||||||
|
type LegacySupabaseService = typeof supabaseService;
|
||||||
|
|
||||||
|
function normalizeUser(row: Partial<UserConfig> | null | undefined): UserConfig | null {
|
||||||
|
const userId = String(row?.user_id || '').trim();
|
||||||
|
if (!userId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
user_id: userId,
|
||||||
|
first_name: String(row?.first_name || ''),
|
||||||
|
last_name: String(row?.last_name || ''),
|
||||||
|
email: String(row?.email || ''),
|
||||||
|
ALPACA_API_KEY: String(row?.ALPACA_API_KEY || ''),
|
||||||
|
ALPACA_SECRET_KEY: String(row?.ALPACA_SECRET_KEY || ''),
|
||||||
|
REAL_ALPACA_API_KEY: String(row?.REAL_ALPACA_API_KEY || ''),
|
||||||
|
REAL_ALPACA_SECRET_KEY: String(row?.REAL_ALPACA_SECRET_KEY || ''),
|
||||||
|
role: String(row?.role || 'member'),
|
||||||
|
trade_enable: Boolean(row?.trade_enable),
|
||||||
|
drop_threshold_for_buy: Number(row?.drop_threshold_for_buy || 0),
|
||||||
|
gain_threshold_for_sell: Number(row?.gain_threshold_for_sell || 0),
|
||||||
|
market_poll_interval_in_seconds: Number(row?.market_poll_interval_in_seconds || 0),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function listActiveTradingUsers(legacyService?: LegacySupabaseService): Promise<UserConfig[]> {
|
||||||
|
const client = legacyService?.getClient?.();
|
||||||
|
if (!client) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const { data, error } = await client
|
||||||
|
.from('users')
|
||||||
|
.select('*')
|
||||||
|
.eq('trade_enable', true);
|
||||||
|
|
||||||
|
if (error || !Array.isArray(data)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
.map((row) => normalizeUser(row as UserConfig))
|
||||||
|
.filter((user): user is UserConfig => Boolean(user));
|
||||||
|
} catch (error) {
|
||||||
|
logger.warn(`[Users] Active trading user lookup failed: ${error instanceof Error ? error.message : 'unknown error'}`);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user