읽기 전용 쿼리 함수와 API 이름
쿼리(Query)는 API Gateway에 선택적으로 공개하는 읽기 전용 함수입니다. 온톨로지를 수정하거나 외부 시스템 상태를 바꾸는 부수 효과를 만들 수 없습니다. API로 편집해야 하는 업무는 액션을 사용합니다.
언어별 공개 방식
TSv1은 Query 데코레이터의 apiName, TSv2는 함수 파일에서 내보낸 config.apiName, Python은 function 데코레이터의 api_name으로 API 이름을 정의합니다. TSv1 Query에 이름을 지정하지 않으면 일반 Function과 비슷하게 동작하며 API 이름으로 노출하지 않습니다.
API 이름은 lowerCamelCase이고 100자 미만이어야 하며 숫자로 시작할 수 없습니다. 저장소로 가져온 온톨로지 범위에서 고유해야 하고 중복이면 태그 과정이 실패합니다. API 이름을 가진 쿼리의 저장소는 최소 한 온톨로지의 엔터티를 가져와야 합니다.
항공기 개수 쿼리
가상의 Aircraft 유형에 다음 비행까지 남은 분을 나타내는 숫자 속성 timeUntilNextFlight가 있다고 가정합니다. 이 함수는 입력한 분보다 많이 남은 항공기를 셉니다. TSv1에서는 해당 속성이 Searchable이어야 합니다.
다음 세 언어 구현은 대안입니다. 같은 온톨로지에 같은 API 이름으로 모두 게시하는 구성은 아닙니다. 각 소비 코드의 입력 이름도 자신이 게시한 구현의 인수와 맞춰야 합니다.
TypeScript v1
import { Query, Double } from "@foundry/functions-api";
import { Objects } from "@foundry/ontology-api";
export class PublishedQueries {
@Query({ apiName: "getReschedulableAircraftCount" })
public async countAircraftTakingOffAfter(minimumTimeInMinutes: Double): Promise<Double> {
const count = await Objects.search().aircraft()
.filter(aircraft => aircraft.timeUntilNextFlight.range().gt(minimumTimeInMinutes))
.count();
return count ?? 0;
}
}
값이 없는 count의 0 처리는 실제 집계가 성공한 이후의 처리입니다. 요청 오류를 0으로 바꾸지는 않습니다. 별도 파일에 두었다면 클래스를 index.ts에서 내보냅니다.
필요한 TSv1 저장소에서는 기존 functions.json에 다음 설정을 병합합니다. 다른 설정을 제거하지 않습니다.
{
"enableQueries": true
}
TypeScript v2
typescript-functions/src/functions/countAircraftTakingOffAfter.ts에 작성합니다.
import { Client } from "@osdk/client";
import { Double } from "@osdk/functions";
import { Aircraft } from "@ontology/sdk";
export const config = { apiName: "getReschedulableAircraftCount" };
export default async function countAircraftTakingOffAfter(
client: Client,
minimumTimeInMinutes: Double
): Promise<Double> {
const { $count } = await client(Aircraft)
.where({ timeUntilNextFlight: { $gt: minimumTimeInMinutes } })
.aggregate({ $select: { $count: "unordered" } });
return $count;
}
Python
from functions.api import Double, function
from ontology_sdk import FoundryClient
from ontology_sdk.ontology.objects import Aircraft
@function(api_name="getReschedulableAircraftCount")
def count_aircraft_taking_off_after(minimum_time_in_minutes: Double) -> Double:
count = (
FoundryClient().ontology.objects.Aircraft
.where(Aircraft.object_type.time_until_next_flight > minimum_time_in_minutes)
.count()
.compute()
)
return float(count)
검색과 API 업데이트
Ontology Manager에서 함수 이름이나 API 이름으로 쿼리를 찾을 수 있습니다. 위 예제의 API 이름은 getReschedulableAircraftCount이며 코드의 함수 이름과 다를 수 있습니다.
API 이름으로 노출한 쿼리는 항상 가장 최근 태그한 게시 버전을 사용하며 일반 함수의 의미적 버전 범위 해소와 다릅니다. 이름을 제거하고 새 태그를 게시하면 API Gateway의 연결을 끊습니다. 이름을 바꾸는 경우에도 기존 소비자가 깨집니다.
소비자가 따로 이전해야 하면 getReschedulableAircraftCountV2처럼 다른 API 이름의 명시적 계약을 별도 함수로 게시할 수 있습니다. 새 코드가 기존 이름에 자동으로 호환된다고 가정하지 않아야 합니다.
다른 함수에서 호출
게시한 쿼리를 소비 저장소의 Resource imports에서 가져온 뒤 바인딩을 생성합니다.
TSv1 소비 예제입니다. Uses는 정적 분석이 놓칠 수 있는 호출을 명시적으로 선언합니다.
import { Double, Function, Uses } from "@foundry/functions-api";
import { Queries } from "@foundry/ontology-api";
export class QueryConsumers {
@Uses({ queries: [Queries.getReschedulableAircraftCount] })
@Function()
public callQueryFunction(): Promise<Double> {
return Queries.getReschedulableAircraftCount(10);
}
}
TSv2 소비 함수는 callQueryFunction.ts에 작성합니다.
import { Client } from "@osdk/client";
import { Double } from "@osdk/functions";
import { getReschedulableAircraftCount } from "@ontology/sdk";
export default async function callQueryFunction(client: Client): Promise<Double> {
return client(getReschedulableAircraftCount).executeFunction({ minimumTimeInMinutes: 10 });
}
Python 구현을 게시한 쿼리의 소비 예제는 다음과 같습니다.
from functions.api import Double, function
from ontology_sdk import FoundryClient
@function
def call_query_function() -> Double:
return FoundryClient().ontology.queries.get_reschedulable_aircraft_count(
minimum_time_in_minutes=10.0
)
TSv1은 게시 함수가 호출할 쿼리와 언어 모델 메서드를 정적 분석으로 찾습니다. 분석이 놓쳐 Uses를 추가하라는 실행 오류가 발생하면 필요한 메서드를 같은 queries 배열에 선언합니다. 모델 메서드도 별도 models 필드가 아니라 이 배열에 넣습니다.
응답과 오류 관측
스트리밍 함수는 결과를 청크로 제공하며 OSDK의 Beta 호출 경로를 사용합니다. 입력이나 업무 조건을 사용자에게 설명할 때는 UserFacingError를 사용하고, 실행 흐름은 로그와 스팬으로 조사할 수 있습니다.