AstroWay/api v2.204.2 · ar
جميع الأنظمة تعمل بشكل طبيعي

X-Cache header: حالة cache-status المرئية لتحسين تكاملات العملاء

كل استجابة API الآن تحمل X-Cache: MISS | HIT | BYPASS - العميل يرى فورًا ما إذا كان الطلب محسوبًا من الصفر أم مستخرجًا من الذاكرة المؤقتة. هذا يفتح عمود نسبة cache hit % في /dashboard/usage ويسمح بتحسين التكامل دون تخمين.

الخادم الجانبي كان يعمل منذ وقت طويل - حساب المخطط المحدد لنفس date/time/lat/lon يُسترجع من الذاكرة المؤقتة، ولا يُعاد حسابه من جديد. لكن العميل ما شاف هذا. في الـ dashboard عمود “cache hit %” كان يظهر – لأن الـ backend كان يسجل cache-outcome في مقياس داخلي، مو في الاستجابة.

الآن كل response يحمل واحد من ثلاثة رؤوس:

X-Cache: HIT # обслужено з кешу
X-Cache: MISS # обчислено з нуля, результат збережено
X-Cache: BYPASS # не кешується за дизайном

هذه تغيير صغير - رأس plus عمود واحد في api_request_log - لكنه يفتح فئة كاملة من التحسينات اللي كانت قبل كده بقعة عمياء.

Terminal window
curl -I -X POST https://api.astroway.info/v1/chart \
-H "X-Api-Key: aw_live_..." \
-H "Content-Type: application/json" \
-d '{
"date": "1990-05-15",
"time": "14:30:00",
"timezoneOffset": 3,
"latitude": 50.45,
"longitude": 30.52
}' | grep -i x-cache
# X-Cache: MISS

نفذ مرة ثانية بنفس جسم الطلب:

Terminal window
# X-Cache: HIT

للـ endpoints من نوع /v1/transits/now (وقت ديناميكي) - X-Cache: BYPASS، لأن النتيجة تعتمد على Date.now() الحالي وما في فائدة من التخزين المؤقت.

مش كل الـ endpoints تُخزن مؤقتًا - وهذا مقصود. التقسيم:

  • حسابات المخطط المحددة (/v1/chart, /v1/houses, /v1/aspects, /v1/synastry, /v1/dasha/*, /v1/vargas/*) - تُخزن بالكامل. نمط متوقع MISS → HIT.
  • معتمد على الوقت (/v1/transits/now, /v1/horoscope/today, /v1/moon/phase-now) - BYPASS. الذاكرة المؤقتة ممكن تكون صحيحة بس لحد دقيقة، فالأبسط ما تخزنها أصلاً.
  • محتوى مولد بالذكاء الاصطناعي (/v1/horoscope/personal, /v1/interpret/*): BYPASS. إجابات الـ LLM غير محددة حتى لو كان الـ prompt نفسه، التخزين المؤقت = تثبيت العشوائية.
  • Endpoints للعرض (/v1/render/*): MISS/HIT لبعضها، BYPASS للّي تستقبل payload كبير (eclipse-path بـ 500 نقطة).

العلامة على الـ endpoint المحدد تظهر مباشرة في الـ response - ما تحتاج تقرأ الوثائق لتعرف إذا كان مخزن مؤقتًا ولا لا.

تأثير التسعير: الطلبات المخزنة مؤقتًا ما زالت تكلف

Section titled “تأثير التسعير: الطلبات المخزنة مؤقتًا ما زالت تكلف”

هذا أهم شيء للفهم - الطلبات المخزنة مؤقتًا تستمر في خصم الcredits من نفس الـ tier مثل الـ MISS. لماذا:

  1. التسعير عندنا مضبوط على قيمة الـ business للـ endpoint، مو على تكلفة الـ CPU. /v1/chart تكلف نفس السعر، سواء أُعيد حساب المخطط أو جاء من الذاكرة المؤقتة - العميل حصل على نفس المخطط.
  2. الشفافية. ما نحبش موقف أحد يدفع لـ MISS والآخر لـ HIT (نظريًا بسبب “حظك مع الذاكرة المؤقتة”). التسعير يكون متوقع.
  3. بنية الذاكرة المؤقتة: هي بنية تحتية، مو قيمة مضافة. إحنا ندعمها في الـ tier.

لكن هذا ما يعني إن X-Cache بلا معنى في سياق التسعير - هو يوضح إمكانيات معمارية للعميل (شوف القسم التالي).

ماذا تفعل بهذا على جانب العميل

Section titled “ماذا تفعل بهذا على جانب العميل”

أربع أنماط عملية:

1. طبقة تخزين مؤقت على جانب العميل لـ MISS

Section titled “1. طبقة تخزين مؤقت على جانب العميل لـ MISS”

إذا شفت X-Cache: MISS لطلب ممكن يتكرر (خريطة ميل لنفس الشخص)، خزن محليًا في Redis/Memcached/IndexedDB. الذاكرة المؤقتة على الخادم عندنا لها TTL وسياسة إخلاء - طبقة العميل مع TTL متحكم فيه بتتفادى خصم الcredits الزايدة.

import { Astroway } from "@astroway/sdk";
const cache = new Redis();
const client = new Astroway({
apiKey: process.env.ASTROWAY_KEY,
// optional: hook on response headers
onResponse(req, res) {
const cacheStatus = res.headers["x-cache"];
metrics.increment(`astroway.cache.${cacheStatus.toLowerCase()}`);
},
});
async function getChart(input: ChartInput) {
const cacheKey = `chart:${hashChart(input)}`;
const cached = await cache.get(cacheKey);
if (cached) return JSON.parse(cached);
const chart = await client.chart.create(input);
await cache.set(cacheKey, JSON.stringify(chart), "EX", 86400);
return chart;
}

2. تجميع + dedupe على الـ backend

Section titled “2. تجميع + dedupe على الـ backend”

إذا خدمتك تستقبل طلبات جماعية على نفس birth-data (حملة onboarding، حيث الزملاء يختبرون ببيانات تجريبية متساوية)، استخدم dedupe على أساس الوعود:

const inFlight = new Map<string, Promise<Chart>>();
function getChart(input: ChartInput) {
const key = hashChart(input);
if (inFlight.has(key)) return inFlight.get(key)!;
const promise = client.chart.create(input);
inFlight.set(key, promise);
promise.finally(() => inFlight.delete(key));
return promise;
}

هذا ما راح يوفر الcredits (كل استدعاء ما زال يُخصم)، لكنه يخفف الازدحام عند انفجارات الـ concurrency.

3. تسخين مسبق للمسارات الحرجة

Section titled “3. تسخين مسبق للمسارات الحرجة”

إذا في المنتج مخططات ريتوالية (أبراج daily-horoscope المشهورة)، سِخّنها مسبقًا بـ cron مجدول. أول طلب في اليوم - MISS، كل البقية لحد الإخلاء - HIT. المستخدم يحصل على استجابة بأقل من ثانية.

4. نظرة من الـ Dashboard: أين تدفع زيادة

Section titled “4. نظرة من الـ Dashboard: أين تدفع زيادة”

العمود الجديد cache hit % في /dashboard/usage لكل endpoint يوضح:

  • HIT% = 90+ - الـ endpoint يتخزن جيدًا، غالبًا نفس المخطط يُعاد إرسالها عدة مرات. فكر في client-side dedupe (#2).
  • HIT% = 0 و BYPASS: الـ endpoint غير مخزن مؤقتًا حسب التصميم (transits/now, AI). هذا طبيعي.
  • HIT% = 50% و MISS: نصف الطلبات تحمل معلمات فريدة، والنصف الآخر تكرارات. يستحق تخزين مؤقت على جانب العميل.
  • HIT% منخفض + endpoint محدد: مريب. تأكد إن عميلك ما يضيف حقول عشوائية في الـ payload (timestamps, request-id) اللي تملأ مفتاح الذاكرة المؤقتة.

التتبع يضيف عمود واحد في api_request_log.cache_status (enum: MISS|HIT|BYPASS, migration 030). العمود يُملأ من نفس الـ handler اللي يقرر عن cache-lookup - ما في طلب إضافي لقاعدة البيانات.

GET /v1/me/usage/endpoints الآن يرجع cache_hit_pct الحقيقي بدلًا من null لكل endpoint في تاريخك. طريقة SDK client.me.usage.endpoints() ستحصل على الحقل تلقائيًا (الأنواع في إصدار codegen القادم).

أدوات قياس الذاكرة المؤقتة تفتح مستوى وسط من التحسينات بين “بدون تخزين مؤقت” و “تخزين كامل على الحافة”. الخطوات القادمة في خارطة الطريق:

  • رأس استجابة Cache-Control مع TTL حقيقي للـ endpoints المخزنة - سيسمح لـ CDN/proxy-cache على جانب العميل
  • If-None-Match ETags: فحص MISS متكرر بدون payload كامل في الاستجابة
  • إحصائيات الذاكرة المؤقتة لكل مستخدم في الـ dashboard مع إمكانية الإبطال (مثلاً، إعادة حساب مخطط معين بعد تعديل birth-time)

الوثائق - /docs/api/ → Performance & Caching. مرجع X-Cache المحدد - في قسم الـ headers لكل endpoint.

MakSeong · AstroWay

أبني AstroWay API: أُغلف Swiss Ephemeris في REST نقي وأكتب عن التفاصيل المملة التي هي فعلاً مهمة.

// ابنِ عليه

نفس Swiss Ephemeris الموجود في Solar Fire - في 4 أسطر من الكود.

مفتاح مجاني بدون بطاقة. 5000 استدعاء شهرياً حتى الدفعة الأولى.

المزيد من المدونة جميع المقالات →

Ephemeris 2026-07-19

كيف نتحكم في الدقة: CI ضد swetest و NASA

الدقة في astro-API تتدهور بسهولة بسبب تعديل واحد في الإيفيميريدات. نستعرض الحماية: نواة واحدة من Swiss Ephemeris للتطبيق وواجهة API، مئات اللقطات المجمدة على خرائط مرجعية وتثليث كل PR ضد swetest CGI و Kerykeion و Prokerala ودليل خسوفات NASA.

Engineering 2026-07-15

ثلاثة SDK رسمية: TypeScript, Python, PHP بدلاً من curl الخام

HTTP الخام يعمل، لكن العميل المطبّق يوفّر ساعات: إكمال تلقائي للمسارات، أنواع الطلب والاستجابة، إعادة محاولة مدمجة على 408/409/429/5xx، وتسلسل أخطاء بنمط Stainless. نستعرض ثلاثة SDK رسمية - @astroway/sdk (npm)، astroway (PyPI)، astroway/sdk (Packagist) - وكيف تم توليدها من عقد OpenAPI واحد.

Industry 2026-06-05

Free Astrology API: Which One Has the Best Free Tier in 2026?

A side-by-side of free tiers across the major astrology APIs - credits, request caps, card requirements - and how much you can actually build for free.