Free lesson · GenAI Platform Engineering
સર્ચ અને ફિલ્ટરિંગ સાથે service catalog REST API બનાવો
service catalog ને platform consumers માટે ઉપલબ્ધ કરાવતું API layer બનાવો. સર્ચ, category દ્વારા ફિલ્ટરિંગ અને versioned catalog responses અમલમાં મૂકો.
Course: AI Developer Platform Engineering · Chapter 1 · Internal Developer Platform Vision
Free to read — no subscription required.
પરિચય
જ્યારે તમે સર્વિસ કેટલોગ પ્રકાશિત કરો છો પણ ઉપભોક્તાઓને તેને ક્વેરી કરવાની કોઈ પ્રોગ્રામેટિક રીત આપતા નથી, ત્યારે ટીમો Git રેપોમાં કાચું YAML વાંચવા, Slack સંદેશાઓના સ્ક્રીનશોટ લેવા, અથવા ટિકિટમાં પ્લેટફોર્મ ટીમને "આપણે કયા વેક્ટર ડેટાબેઝ ઓફર કરીએ છીએ?" એવું પૂછવા તરફ વળે છે. કેટલોગ ડેટા અસ્તિત્વમાં છે, પણ તે શોધી શકાય તેવો નથી—એન્જિનિયરો માનવ હસ્તક્ષેપ વિના "team-beta ની માલિકીની દરેક GPU-આધારિત મોડેલ-સર્વિંગ એન્ટ્રી મને બતાવો, સૌથી નવું વર્ઝન પહેલાં" એવા પ્રશ્નનો જવાબ મેળવી શકતા નથી. API સ્તર આ અંતર પૂરે છે: તે કેટલોગને HTTP પર સ્ટ્રક્ચર્ડ સર્ચ, કેટેગરી ફિલ્ટરિંગ, પેજિનેશન અને સ્પષ્ટ રિસ્પોન્સ વર્ઝન સાથે ઉપલબ્ધ કરે છે, જેથી ડેવલપર પોર્ટલ, CLI અને CI પાઇપલાઇન બધા એક જ કોન્ટ્રાક્ટનો ઉપયોગ કરી શકે. આ પાઠના અંતે, તમે ઉપભોક્તાના ઇનપુટને માન્ય કરતી ક્વેરી અને રિસ્પોન્સ સ્કીમા વ્યાખ્યાયિત કરી શકશો, કેટલોગ સ્ટોર પર ચાલતું ફુલ-ટેક્સ્ટ સર્ચ અને કેટેગરી ફિલ્ટર અમલમાં મૂકી શકશો, અને પરિણામોને એક વર્ઝન્ડ એન્વલપમાં લપેટી શકશો જે તમને હાલના ક્લાયન્ટ્સને તોડ્યા વિના પેલોડનો આકાર વિકસાવવા દે છે.
મુખ્ય પરિભાષા
- Catalog API: HTTP ઇન્ટરફેસ જે સર્વિસ કેટલોગ પર વાંચન કામગીરીઓ—લિસ્ટિંગ, સર્ચિંગ, ફિલ્ટરિંગ અને વ્યક્તિગત એન્ટ્રી મેળવવી—પ્લેટફોર્મ ઉપભોક્તાઓ માટે ઉપલબ્ધ કરે છે.
- Query Parameter Model: એક માન્ય કરેલી સ્કીમા (
CatalogQuery) જે URL ક્વેરી સ્ટ્રિંગ દલીલોને ટાઇપ કરેલા ફીલ્ડ સાથે બાંધે છે, અને કોઈપણ સ્ટોર એક્સેસ પહેલાં ખોટી રચનાવાળી વિનંતીઓને નકારે છે. - Response Envelope: એક રેપર ઓબ્જેક્ટ (
CatalogListResponse) જે પરિણામ આઇટમો સાથે કુલ ગણતરી, પેજિનેશન કર્સર અને API વર્ઝન જેવા મેટાડેટા વહન કરે છે. - API Versioning: દરેક રિસ્પોન્સમાં સ્પષ્ટ
api_versionફીલ્ડ સમાવવું, જેથી ઉપભોક્તાઓ ચૂપચાપ તૂટવાને બદલે સ્કીમા બદલાવોને શોધી શકે અને તેને અનુકૂળ થઈ શકે. - Category Filter: એક સર્વર-સાઇડ પ્રેડિકેટ જે પરિણામોને
ServiceCategoryસાથે મેળ ખાતી એન્ટ્રીઓ સુધી સંકુચિત કરે છે, અને ગણતરીઓ સચોટ રહે તે માટે પેજિનેશન પહેલાં લાગુ થાય છે.
વિભાવનાઓ
હવે આપણી પાસે ઉપલબ્ધ કરવા માટે કેટલોગ ડેટા મોડેલ છે, ત્યારે API સ્તર પ્લેટફોર્મ ઉપભોક્તાઓ અને અંતર્ગત એન્ટ્રી સ્ટોર વચ્ચે બેસે છે, અને ઢીલા-ટાઇપવાળી HTTP ક્વેરી સ્ટ્રિંગ્સને માન્ય કરેલા, ફિલ્ટર કરેલા, વર્ઝન્ડ રિસ્પોન્સમાં રૂપાંતરિત કરે છે. એક વિનંતી ચાર તબક્કામાંથી વહે છે: ઇનપુટ બાઇન્ડિંગ, ફિલ્ટરિંગ, પેજિનેશન અને એન્વલપ નિર્માણ. દરેક તબક્કાની એક જ જવાબદારી છે, અને તેમને અલગ રાખવાથી જ સર્ચ એન્ડપોઇન્ટ ટેસ્ટ કરી શકાય તેવો અને રિસ્પોન્સનો આકાર વિકસાવી શકાય તેવો બને છે.
ઇનપુટ બાઇન્ડિંગ તબક્કો ?q=qdrant&category=vector-db&limit=20&offset=0 ને CatalogQuery ઇન્સ્ટન્સ પર મેપ કરે છે. ટાઇપ કરેલા મોડેલ દ્વારા બાઇન્ડિંગ કરવાનો અર્થ એ છે કે અમાન્ય limit (નકારાત્મક, અથવા મર્યાદાથી ઉપર) આપમેળે 422 સાથે નકારાય છે—એન્ડપોઇન્ટ બોડી ખરાબ ઇનપુટ સામે કદી ચાલતી નથી. ફિલ્ટરિંગ તબક્કો બે સ્વતંત્ર પ્રેડિકેટ લાગુ કરે છે: q શબ્દ માટે એન્ટ્રીના name અને description સામે કેસ-અસંવેદનશીલ સબસ્ટ્રિંગ મેચ, અને category માટે ચોક્કસ service_type મેચ. બંને વૈકલ્પિક છે; કોઈ એકને છોડી દેવાથી ભૂલ થવાને બદલે પરિણામ સમૂહ વિસ્તરે છે.
છેલ્લા બે તબક્કાઓ વચ્ચેનો ક્રમ મહત્વનો છે. ફિલ્ટરિંગ પેજિનેશન પહેલાં પૂર્ણ થવું જોઈએ, જેથી total મેળ ખાતી એન્ટ્રીઓની ગણતરી દર્શાવે, બધી એન્ટ્રીઓની નહીં. જો તમે પહેલા પેજિનેટ કરો અને પછી પેજને ફિલ્ટર કરો, તો સર્ચનું બીજું પેજ એ મેચો ચૂપચાપ છોડી દે છે જે યોગાનુયોગ પહેલા પેજ પર આવી ગઈ હતી, અને total અર્થહીન બને છે. સમગ્ર સમૂહ પર apply_filters ચલાવવું, ફિલ્ટર કરેલી લંબાઈથી total ગણવું, અને તે પછી જ paginate સાથે સ્લાઇસ કરવું—આ પેજિનેશન મેટાડેટાને પ્રામાણિક રાખે છે.
રિસ્પોન્સ એન્વલપ એ છે જ્યાં વર્ઝનિંગ રહે છે. માત્ર JSON એરે પરત કરવાને બદલે, list_services એક CatalogListResponse પરત કરે છે જે api_version, items, total, limit અને offset વહન કરે છે. ઉપભોક્તાઓ api_version વાંચીને નક્કી કરે છે કે તેઓ પેલોડ સમજે છે કે નહીં. જ્યારે તમે પછીથી કોઈ ફીલ્ડ ઉમેરો—કહો કે deprecation_notice—ત્યારે api_version "v1" પર પિન કરેલા જૂના ક્લાયન્ટ્સ કામ કરતા રહે છે, કારણ કે એક વર્ઝનની અંદર ઉમેરાત્મક બદલાવો સુરક્ષિત છે, અને બ્રેકિંગ બદલાવ વર્ઝન વધારે છે જેથી ક્લાયન્ટ્સ તેના પર બ્રાન્ચ કરી શકે. આ એ જ શિસ્ત છે જે તમે કેટલોગ એન્ટ્રીઓ પર પોતે લાગુ કરો છો, ટ્રાન્સપોર્ટ સ્તર સુધી વિસ્તારેલી.
કોડ વોકથ્રુ
ચાર-તબક્કાના વિનંતી પ્રવાહની સમીક્ષા કર્યા પછી, નીચેનું અમલીકરણ તેને બે ભાગોમાં એન્કોડ કરે છે: HTTP કોન્ટ્રાક્ટને બાંધતી અને માન્ય કરતી વિનંતી/રિસ્પોન્સ સ્કીમા, અને FastAPI રાઉટર જે સર્ચ, ફિલ્ટરિંગ અને પેજિનેશનને બે એન્ડપોઇન્ટમાં જોડે છે. પહેલો બ્લોક ServiceCategory, CatalogQuery ઇનપુટ મોડેલ, પ્રતિ-આઇટમ CatalogItemResponse, અને વર્ઝન્ડ CatalogListResponse એન્વલપ વ્યાખ્યાયિત કરે છે—દરેક ફીલ્ડ એવી રીતે બંધાયેલું છે કે ખોટી રચનાવાળી વિનંતીઓ હેન્ડલરની ઊંડાઈમાં નહીં પણ બાઇન્ડિંગ સમયે જ નિષ્ફળ થાય.
Code snippetpython
1from pydantic import BaseModel, Field 2from enum import Enum 3from typing import Optional 4 5CATALOG_API_VERSION = "v1" 6 7class ServiceCategory(str, Enum): 8 MODEL_SERVING = "model-serving" 9 TRAINING_JOB = "training-job" 10 VECTOR_DB = "vector-db" 11 FEATURE_STORE = "feature-store" 12 MONITORING = "monitoring" 13 14class CatalogQuery(BaseModel): 15 q: Optional[str] = Field(default=None, max_length=128) 16 category: Optional[ServiceCategory] = None 17 limit: int = Field(default=25, ge=1, le=100) 18 offset: int = Field(default=0, ge=0) 19 20class CatalogItemResponse(BaseModel): 21 service_id: str 22 name: str 23 service_type: ServiceCategory 24 version: str 25 owner_team: str 26 description: str 27 deprecated: bool 28 29class CatalogListResponse(BaseModel): 30 api_version: str = CATALOG_API_VERSION 31 total: int 32 limit: int 33 offset: int 34 items: list[CatalogItemResponse]
- લાઇન 6-12:
ServiceCategoryકેટલોગની સર્વિસ-ટાઇપ વર્ગીકરણ પદ્ધતિના જ kebab-case મૂલ્યોનો પુનઃઉપયોગ કરે છે, જેથી વાસ્તવિક કેટેગરી ન હોય તેવુંcategoryક્વેરી પેરામીટર બાઇન્ડિંગ સમયે જ નકારાય—હેન્ડલરની અંદર તેને હાથે માન્ય કરવાની જરૂર નથી. - લાઇન 14-18:
CatalogQuerylimitને[1, 100]સુધી અનેoffsetને≥ 0સુધી મર્યાદિત કરે છે.limit=5000માંગતા ક્લાયન્ટને 422 મળે છે, જે સ્ટોરને અમર્યાદિત સ્કેનથી બચાવે છે; બંને સર્ચ ફીલ્ડ ડિફોલ્ટNoneછે, જેથી દલીલ વગરની વિનંતી બધાનું પહેલું પેજ પરત કરે. - લાઇન 28-33:
CatalogListResponseapi_versionને ડિફોલ્ટCATALOG_API_VERSIONપર રાખે છે, જેથી દરેક રિસ્પોન્સ સ્વ-વર્ણનાત્મક હોય;totalitemsની બાજુમાં બેસે છે જેથી ઉપભોક્તાઓ બીજા કોલ વિના ગણી શકે કે કેટલાં પેજ બાકી છે.
બીજો બ્લોક ફિલ્ટરિંગ અને પેજિનેશનના શુદ્ધ ફંક્શન્સ તથા બે એન્ડપોઇન્ટ અમલમાં મૂકે છે. apply_filters સંપૂર્ણ એન્ટ્રી સમૂહ પર બંને પ્રેડિકેટ ચલાવે છે; paginate ફિલ્ટર કરેલી યાદીને સ્લાઇસ કરે છે; list_services તેમને જોડે છે અને એન્વલપ બનાવે છે; get_service એક-એન્ટ્રી લુકઅપ સંભાળે છે અને service_id અજાણ્યું હોય ત્યારે 404 raise કરે છે.
Code snippetpython
1from fastapi import APIRouter, Depends, HTTPException 2 3router = APIRouter(prefix="/catalog", tags=["catalog"]) 4 5def apply_filters(entries: list, query: CatalogQuery) -> list: 6 results = entries 7 if query.category is not None: 8 results = [e for e in results if e.service_type == query.category] 9 if query.q: 10 term = query.q.lower() 11 results = [ 12 e for e in results 13 if term in e.name.lower() or term in e.description.lower() 14 ] 15 return results 16 17def paginate(entries: list, limit: int, offset: int) -> list: 18 return entries[offset : offset + limit] 19 20@router.get("", response_model=CatalogListResponse) 21def list_services(query: CatalogQuery = Depends(), store=Depends(get_catalog_store)): 22 matched = apply_filters(store.all_entries(), query) 23 page = paginate(matched, query.limit, query.offset) 24 return CatalogListResponse( 25 total=len(matched), 26 limit=query.limit, 27 offset=query.offset, 28 items=[CatalogItemResponse(**e.model_dump()) for e in page], 29 ) 30 31@router.get("/{service_id}", response_model=CatalogItemResponse) 32def get_service(service_id: str, store=Depends(get_catalog_store)): 33 entry = store.get(service_id) 34 if entry is None: 35 raise HTTPException(status_code=404, detail=f"unknown service_id: {service_id}") 36 return CatalogItemResponse(**entry.model_dump())
- લાઇન 5-15:
apply_filtersપહેલાં કેટેગરી પ્રેડિકેટ (સસ્તી ચોક્કસ મેચ) લાગુ કરે છે, પછી સબસ્ટ્રિંગ સર્ચ; બંનેis not None/ સત્યતા-તપાસથી સુરક્ષિત છે, જેથી છોડી દેવાયેલું પેરામીટર કંઈ ન કરતી કામગીરી બને જે પરિણામો વિસ્તારે, શૂન્ય સુધી ફિલ્ટર ન કરે. - લાઇન 22-30:
list_servicesસમગ્ર સમૂહ પરmatchedગણે છે, સ્લાઇસ કરતાં પહેલાંlen(matched)થીtotalમેળવે છે, પછી પેજિનેટ કરે છે—આ ખાતરી આપે છે કે એન્વલપનુંtotalમેચોની ગણતરી કરે છે, કાચા કેટલોગના કદની નહીં. - લાઇન 33-38:
get_serviceએક એન્ટ્રી પરત કરે છે અથવા 404 સાથેHTTPExceptionraiseકરે છે;Noneપરત કરવાથી FastAPI null બોડી સિરિયલાઇઝ કરી દેત, તેથી સ્પષ્ટ raise જ ઉપભોક્તાઓને કાર્યક્ષમ ભૂલ આપે છે.
ચકાસણી માટે GET /catalog?category=vector-db&q=qdrant&limit=5 જારી કરો—રિસ્પોન્સમાં api_version: "v1", મેળ ખાતી vector-db એન્ટ્રીઓ જેમના name અથવા description માં "qdrant" હોય તેની સંખ્યા જેટલું total, અને વધુમાં વધુ પાંચ items હોવા જોઈએ; પછી GET /catalog/does-not-exist એ unknown service_id વિગત સાથે 404 પરત કરવું જોઈએ.
શિસ્ત-વિશિષ્ટ ઉપયોગ
શું કરવું અને શું ન કરવું
ઉપર ક્વેરી સ્કીમા, ફિલ્ટર-પછી-પેજિનેટ પાઇપલાઇન અને વર્ઝન્ડ એન્વલપમાંથી પસાર થયા બાદ, નીચેના આદેશો API-કોન્ટ્રાક્ટ અને સર્ચ-સચોટતાની પેટર્નને એવા નિયમોમાં સંક્ષિપ્ત કરે છે જે તમે તમારા પોતાના કેટલોગ એન્ડપોઇન્ટ બનાવતી વખતે સીધા લાગુ કરી શકો.
શું કરવું
- ક્વેરી સ્ટ્રિંગ્સને
Depends()સાથેCatalogQueryમોડેલ દ્વારા બાંધો —Fieldમર્યાદાઓ (limit[1, 100]માં,offset ≥ 0,categoryએકServiceCategoryતરીકે)list_servicesચાલે તે પહેલાં ખોટી રચનાવાળી વિનંતીઓને 422 સાથે નકારે છે, જેથી કોઈ હેન્ડલર કોડ કદી અમર્યાદિત limit અથવા અજાણી કેટેગરી સ્ટ્રિંગ સામે ચાલતો નથી. apply_filtersસંપૂર્ણ એન્ટ્રી સમૂહ પર ચલાવો અનેpaginateકોલ કરતાં પહેલાંlen(matched)થીtotalમેળવો — ફિલ્ટર કરેલી પણ સ્લાઇસ ન કરેલી યાદી પર ગણતરી કરવાથીCatalogListResponse.totalફીલ્ડ પ્રામાણિક રહે છે, જેથી ઉપભોક્તાઓ મેચો ચૂપચાપ ગુમાવ્યા વિના સર્ચ પરિણામોમાંથી પેજ-દર-પેજ પસાર થઈ શકે.- દરેક રિસ્પોન્સ પર
CATALOG_API_VERSIONમાંથીapi_versionમૂકો — સ્વ-વર્ણનાત્મક એન્વલપ પોર્ટલ અને CI ક્લાયન્ટ્સને વર્ઝન પર બ્રાન્ચ કરવા દે છે, અને તમને"v1"ની અંદર ઉમેરાત્મક રીતે ફીલ્ડ ઉમેરવા દે છે, જ્યારે બ્રેકિંગ પેલોડ બદલાવો માટે વર્ઝન વધારો અનામત રાખે છે.
શું ન કરવું
- ફિલ્ટરિંગ પહેલાં પેજિનેટ ન કરો — પહેલાં
store.all_entries()ને સ્લાઇસ કરવું અને પછી પેજ પરapply_filtersચલાવવુંtotalને અર્થહીન બનાવે છે અને વર્તમાન વિન્ડો બહાર આવતી મેચો છોડી દે છે; પાઇપલાઇનનો ક્રમ (apply_filters→paginate) જ સાચી ગણતરીઓ અને સંપૂર્ણ પરિણામ સમૂહની ખાતરી આપે છે. list_servicesમાંથી માત્ર યાદી પરત ન કરો —CatalogListResponseએન્વલપ છોડી દેવાથીapi_version,totalઅનેoffsetનીકળી જાય છે, અને ઉપભોક્તાઓ પાસે સ્કીમા બદલાવો શોધવાની કે પેજિનેશન ચલાવવાની કોઈ રીત રહેતી નથી—જે બરાબર એ જ શોધક્ષમતાનું અંતર છે જે API પૂરવા માટે બન્યું છે.- ખૂટતા
service_idમાટેget_serviceમાંથીreturn Noneન કરો — null બોડીnullસાથે 200 તરીકે સિરિયલાઇઝ થાય છે, જે ભૂલ છુપાવે છે;HTTPException(status_code=404, ...)raiseકરવું ઉપભોક્તાઓને કાર્યક્ષમ, યોગ્ય કોડવાળી નિષ્ફળતા આપે છે જેના પર તેઓ બ્રાન્ચ કરી શકે.
3 hands-on labs come with this lesson — real code, in a cloud IDE. Create a free account to run them. No card.
Free account · no card · straight to the labs
Or get the full path — from
Listen to this lesson
Audio overviews of this lesson's labs and its chapter, from GenBodha Bytes.
- Implement catalog listing with paginationLab6 min
- Add full-text search across catalog entriesLab6 min
- Build catalog versioning with ETagsLab6 min
- Internal Developer Platform VisionChapter overview19 min
More free lessons in AI Developer Platform Engineering
- Ch 1Design service catalog data model and golden path templates
- Ch 1Build service catalog REST API with search and filteringYou are here
- Ch 1Integrate platform with Kubernetes cluster discovery
- Ch 1Build platform health dashboard with Prometheus metrics
- Ch 1Deploy platform control plane with Helm and ArgoCD
- Ch 2Integrate service mesh with Kubernetes endpoints
- Ch 4Add request logging with PII redaction pipeline