Refactor getService() method for better maintainability

Break down 138-line method with three helper functions:

1. filterCompatibleServices(): Eliminates duplicate filtering logic
   - Used in both paginated and random discovery modes
   - Centralizes version compatibility checking

2. findAvailableOffer(): Encapsulates offer lookup logic
   - Used across all three modes
   - Ensures consistent offer selection

3. buildServiceResponse(): Standardizes response formatting
   - Single source of truth for response structure
   - Used in all return paths

Benefits:
- Eliminates 30+ lines of duplicate code
- Three modes now clearly separated and documented
- Easier to maintain and test each mode independently
- Consistent response formatting across all modes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2025-12-12 23:09:24 +01:00
parent 3c0d1c8411
commit 88a038a12a

View File

@@ -154,7 +154,10 @@ const handlers: Record<string, RpcHandler> = {
}, },
/** /**
* Get service by FQN * Get service by FQN - Supports 3 modes:
* 1. Direct lookup: FQN includes @username
* 2. Paginated discovery: FQN without @username, with limit/offset
* 3. Random discovery: FQN without @username, no limit
*/ */
async getService(params, message, signature, publicKey, storage, config) { async getService(params, message, signature, publicKey, storage, config) {
const { serviceFqn, limit, offset } = params; const { serviceFqn, limit, offset } = params;
@@ -179,50 +182,59 @@ const handlers: Record<string, RpcHandler> = {
throw new Error('Failed to parse service FQN'); throw new Error('Failed to parse service FQN');
} }
// Paginated discovery mode // Helper: Filter services by version compatibility
if (limit !== undefined) { const filterCompatibleServices = (services) => {
const pageLimit = Math.min(Math.max(1, limit), MAX_PAGE_SIZE); return services.filter((s) => {
const pageOffset = Math.max(0, offset || 0);
const allServices = await storage.getServicesByName(
parsed.service,
parsed.version
);
const compatibleServices = allServices.filter((s) => {
const serviceVersion = parseServiceFqn(s.serviceFqn); const serviceVersion = parseServiceFqn(s.serviceFqn);
return ( return (
serviceVersion && serviceVersion &&
isVersionCompatible(parsed.version, serviceVersion.version) isVersionCompatible(parsed.version, serviceVersion.version)
); );
}); });
};
// Helper: Find available offer for service
const findAvailableOffer = async (service) => {
const offers = await storage.getOffersForService(service.id);
return offers.find((o) => !o.answererUsername);
};
// Helper: Build service response object
const buildServiceResponse = (service, offer) => ({
serviceId: service.id,
username: service.username,
serviceFqn: service.serviceFqn,
offerId: offer.id,
sdp: offer.sdp,
createdAt: service.createdAt,
expiresAt: service.expiresAt,
});
// Mode 1: Paginated discovery
if (limit !== undefined) {
const pageLimit = Math.min(Math.max(1, limit), MAX_PAGE_SIZE);
const pageOffset = Math.max(0, offset || 0);
const allServices = await storage.getServicesByName(parsed.service, parsed.version);
const compatibleServices = filterCompatibleServices(allServices);
// Get unique services per username with available offers
const usernameSet = new Set<string>(); const usernameSet = new Set<string>();
const uniqueServices: any[] = []; const uniqueServices: any[] = [];
for (const service of compatibleServices) { for (const service of compatibleServices) {
if (!usernameSet.has(service.username)) { if (!usernameSet.has(service.username)) {
usernameSet.add(service.username); usernameSet.add(service.username);
const offers = await storage.getOffersForService(service.id); const availableOffer = await findAvailableOffer(service);
const availableOffer = offers.find((o) => !o.answererUsername);
if (availableOffer) { if (availableOffer) {
uniqueServices.push({ uniqueServices.push(buildServiceResponse(service, availableOffer));
serviceId: service.id,
username: service.username,
serviceFqn: service.serviceFqn,
offerId: availableOffer.id,
sdp: availableOffer.sdp,
createdAt: service.createdAt,
expiresAt: service.expiresAt,
});
} }
} }
} }
const paginatedServices = uniqueServices.slice( // Paginate results
pageOffset, const paginatedServices = uniqueServices.slice(pageOffset, pageOffset + pageLimit);
pageOffset + pageLimit
);
return { return {
services: paginatedServices, services: paginatedServices,
@@ -232,68 +244,37 @@ const handlers: Record<string, RpcHandler> = {
}; };
} }
// Direct lookup with username // Mode 2: Direct lookup with username
if (parsed.username) { if (parsed.username) {
const service = await storage.getServiceByFqn(serviceFqn); const service = await storage.getServiceByFqn(serviceFqn);
if (!service) { if (!service) {
throw new Error('Service not found'); throw new Error('Service not found');
} }
const offers = await storage.getOffersForService(service.id); const availableOffer = await findAvailableOffer(service);
const availableOffer = offers.find((o) => !o.answererUsername);
if (!availableOffer) { if (!availableOffer) {
throw new Error('Service has no available offers'); throw new Error('Service has no available offers');
} }
return { return buildServiceResponse(service, availableOffer);
serviceId: service.id,
username: service.username,
serviceFqn: service.serviceFqn,
offerId: availableOffer.id,
sdp: availableOffer.sdp,
createdAt: service.createdAt,
expiresAt: service.expiresAt,
};
} }
// Random discovery without username // Mode 3: Random discovery without username
const allServices = await storage.getServicesByName( const allServices = await storage.getServicesByName(parsed.service, parsed.version);
parsed.service, const compatibleServices = filterCompatibleServices(allServices);
parsed.version
);
const compatibleServices = allServices.filter((s) => {
const serviceVersion = parseServiceFqn(s.serviceFqn);
return (
serviceVersion &&
isVersionCompatible(parsed.version, serviceVersion.version)
);
});
if (compatibleServices.length === 0) { if (compatibleServices.length === 0) {
throw new Error('No services found'); throw new Error('No services found');
} }
const randomService = const randomService = compatibleServices[Math.floor(Math.random() * compatibleServices.length)];
compatibleServices[ const availableOffer = await findAvailableOffer(randomService);
Math.floor(Math.random() * compatibleServices.length)
];
const offers = await storage.getOffersForService(randomService.id);
const availableOffer = offers.find((o) => !o.answererUsername);
if (!availableOffer) { if (!availableOffer) {
throw new Error('Service has no available offers'); throw new Error('Service has no available offers');
} }
return { return buildServiceResponse(randomService, availableOffer);
serviceId: randomService.id,
username: randomService.username,
serviceFqn: randomService.serviceFqn,
offerId: availableOffer.id,
sdp: availableOffer.sdp,
createdAt: randomService.createdAt,
expiresAt: randomService.expiresAt,
};
}, },
/** /**