"""Async catalog search PoC using Quart + asyncpg. Run: hypercorn async_catalog:app --bind 0.0.0.0:5002 Endpoint: GET /pos/api/catalog/async-search?q=filtro&limit=50&tenant_id=1 This demonstrates I/O non-blocking search using asyncpg. """ import os import asyncio import asyncpg from quart import Quart, request, jsonify, g app = Quart(__name__) MASTER_DB_URL = os.environ.get('MASTER_DB_URL', 'postgresql://postgres@/nexus_autoparts') # Shared connection pool _pool = None async def _get_pool(): global _pool if _pool is None: _pool = await asyncpg.create_pool(MASTER_DB_URL, min_size=2, max_size=10) return _pool @app.before_serving async def startup(): await _get_pool() @app.after_serving async def shutdown(): global _pool if _pool: await _pool.close() _pool = None @app.route('/pos/api/catalog/async-search') async def async_search(): q = request.args.get('q', '').strip() if not q or len(q) < 2: return jsonify({'data': []}) limit = min(request.args.get('limit', 50, type=int), 100) pool = await _get_pool() async with pool.acquire() as conn: # Simple text search (PoC scope) clean_q = q.upper().replace(' ', '') rows = await conn.fetch(""" SELECT p.id_part, p.oem_part_number, p.name_part, p.name_es, p.image_url, p.group_id FROM parts p WHERE REPLACE(UPPER(p.oem_part_number), ' ', '') LIKE $1 OR p.name_part ILIKE $2 OR p.name_es ILIKE $2 ORDER BY p.oem_part_number LIMIT $3 """, f'%{clean_q}%', f'%{q}%', limit) part_ids = [r['id_part'] for r in rows] vehicle_map = {} if part_ids: vrows = await conn.fetch(""" SELECT part_id, name_brand, name_model, year_car FROM part_vehicle_preview WHERE part_id = ANY($1) """, part_ids) for vr in vrows: vehicle_map[vr['part_id']] = f"{vr['name_brand']} {vr['name_model']} {vr['year_car']}" results = [] for r in rows: results.append({ 'id': r['id_part'], 'oem_part_number': r['oem_part_number'], 'name': r['name_part'], 'name_es': r['name_es'], 'image_url': r['image_url'], 'group_id': r['group_id'], 'vehicle_info': vehicle_map.get(r['id_part'], ''), }) return jsonify({'data': results}) if __name__ == '__main__': app.run(host='0.0.0.0', port=5002)