Carregando
Aula 2 - Módulo 7: Distribuição global e otimização de latência
Edge functions executam próximo aos usuários, reduzindo latência de centenas para dezenas de milissegundos. Para aplicações tRPC críticas, isso significa UX superior.
CDN inteligente distribui código e dados globalmente, garantindo performance consistente independente da localização do usuário.
Edge computing escala automaticamente baseado na demanda regional, otimizando custos e garantindo disponibilidade global.
Cache distribuído no edge reduz carga nos servidores origin e acelera responses para queries frequentes.
Edge Functions:
Código executado em edge locations próximas aos usuários
CDN:
Content Delivery Network para cache e distribuição
Edge Cache:
Cache distribuído em múltiplas regiões
Cold Start:
Tempo inicial de carregamento de functions
// 📁 edge/cloudflare-worker.ts
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
import type { AppRouter } from '../server/api/root';
// 🌍 Edge-optimized tRPC client
const createEdgeClient = (region: string) => {
return createTRPCProxyClient<AppRouter>({
links: [
httpBatchLink({
url: `https://api-${region}.trpc-app.com/trpc`,
headers: {
'CF-Ray': self.CF_RAY || '',
'CF-IPCountry': self.CF_IPCountry || '',
},
}),
],
});
};
// 🎯 Main edge function
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const userCountry = request.headers.get('CF-IPCountry') || 'US';
const userRegion = getOptimalRegion(userCountry);
// 🔍 Route based on request type
if (url.pathname.startsWith('/api/trpc')) {
return handleTRPCRequest(request, userRegion, env, ctx);
}
if (url.pathname.startsWith('/edge-cache')) {
return handleCacheRequest(request, env, ctx);
}
return new Response('Not Found', { status: 404 });
},
};
// 🎯 Handle tRPC requests at the edge
async function handleTRPCRequest(
request: Request,
region: string,
env: Env,
ctx: ExecutionContext
): Promise<Response> {
const url = new URL(request.url);
const procedure = url.pathname.replace('/api/trpc/', '');
const cacheKey = `trpc:${procedure}:${url.search}`;
// 🗂️ Try edge cache first
const cached = await env.EDGE_CACHE.get(cacheKey);
if (cached) {
console.log(`🎯 Edge cache HIT: ${procedure}`);
return new Response(cached, {
headers: {
'Content-Type': 'application/json',
'Cache-Control': 'public, max-age=60',
'X-Cache': 'HIT',
},
});
}
console.log(`❌ Edge cache MISS: ${procedure}`);
try {
// 🔄 Proxy to optimal region
const client = createEdgeClient(region);
const startTime = Date.now();
// 📊 Execute based on request method
let result;
if (request.method === 'GET') {
const input = url.searchParams.get('input');
const parsedInput = input ? JSON.parse(input) : undefined;
result = await (client as any)[procedure].query(parsedInput);
} else if (request.method === 'POST') {
const body = await request.json();
result = await (client as any)[procedure].mutate(body);
}
const duration = Date.now() - startTime;
// 💾 Cache successful responses
if (request.method === 'GET' && result) {
const ttl = getCacheTTL(procedure);
ctx.waitUntil(
env.EDGE_CACHE.put(cacheKey, JSON.stringify(result), {
expirationTtl: ttl
})
);
}
// 📊 Record metrics
ctx.waitUntil(recordMetrics(procedure, duration, region, env));
return new Response(JSON.stringify(result), {
headers: {
'Content-Type': 'application/json',
'Cache-Control': `public, max-age=${getCacheTTL(procedure)}`,
'X-Cache': 'MISS',
'X-Region': region,
'X-Duration': `${duration}ms`,
},
});
} catch (error) {
console.error(`Edge function error:`, error);
return new Response(JSON.stringify({
error: 'Internal Server Error',
code: 'EDGE_ERROR'
}), {
status: 500,
headers: { 'Content-Type': 'application/json' },
});
}
}
// 🌍 Determine optimal region for user
function getOptimalRegion(country: string): string {
const regionMap: Record<string, string> = {
// North America
'US': 'us-east-1',
'CA': 'us-east-1',
'MX': 'us-east-1',
// Europe
'GB': 'eu-west-1',
'DE': 'eu-west-1',
'FR': 'eu-west-1',
'IT': 'eu-west-1',
'ES': 'eu-west-1',
// Asia Pacific
'JP': 'ap-northeast-1',
'KR': 'ap-northeast-1',
'SG': 'ap-southeast-1',
'AU': 'ap-southeast-2',
'IN': 'ap-south-1',
// South America
'BR': 'sa-east-1',
'AR': 'sa-east-1',
};
return regionMap[country] || 'us-east-1';
}
// 🕐 Get cache TTL based on procedure type
function getCacheTTL(procedure: string): number {
const ttlMap: Record<string, number> = {
'user.getProfile': 300, // 5 minutes
'post.getById': 600, // 10 minutes
'post.getRecent': 60, // 1 minute
'auth.getSession': 0, // No cache
'analytics.track': 0, // No cache
};
// Default cache for GET operations
return ttlMap[procedure] || 180; // 3 minutes default
}
// 📊 Record edge metrics
async function recordMetrics(
procedure: string,
duration: number,
region: string,
env: Env
): Promise<void> {
const metrics = {
timestamp: Date.now(),
procedure,
duration,
region,
datacenter: env.CF_RAY?.split('-')[1] || 'unknown',
};
// Send to analytics
await env.ANALYTICS.writeDataPoint(metrics);
}Na próxima aula, vamos explorar Edge Computing e CDN, implementando aplicações tRPC distribuídas globalmente com edge functions e cache inteligente.