6.6. TypeScript 関数の開発

TypeScript 関数プロジェクトを作成 したら、指定のテンプレートを変更して、関数にビジネスロジックを追加できます。これには、関数呼び出しと返されるヘッダーとステータスコードの設定が含まれます。

6.6.1. 前提条件

6.6.2. Typescript 関数テンプレートの構造

Knative (kn) CLI を使用して TypeScript 関数を作成すると、プロジェクトディレクトリーは典型的な TypeScript プロジェクトのようになります。唯一の例外は、関数の設定に使用される追加の func.yaml ファイルです。

http および event トリガー関数のテンプレート構造はいずれも同じです。

テンプレート構造

.
├── func.yaml 1
├── package.json 2
├── package-lock.json
├── README.md
├── src
│   └── index.ts 3
├── test 4
│   ├── integration.ts
│   └── unit.ts
└── tsconfig.json

1
func.yaml 設定ファイルは、イメージ名とレジストリーを判断するために使用されます。
2
テンプレート package.json ファイルにある依存関係に限定されるわけではありません。他の TypeScript プロジェクトと同様に、別の依存関係を追加できます。

npm 依存関係の追加例

npm install --save opossum

デプロイメント用にプロジェクトをビルドすると、これらの依存関係は作成したランタイムコンテナーイメージに含まれます。

3
プロジェクトには、handle という名前の関数をエクスポートする src/index.js ファイルが含まれている必要があります。
4
統合およびテストスクリプトは、関数テンプレートの一部として提供されます。

6.6.3. TypeScript 関数の呼び出しについて

Knative (kn) CLI を使用して関数プロジェクトを作成する場合に、CloudEvents に応答するプロジェクト、または単純な HTTP 要求に応答するプロジェクトを生成できます。Knative の CloudEvents は HTTP 経由で POST 要求として転送されるため、関数タイプはいずれも受信 HTTP イベントをリッスンして応答します。

Typescript 関数は、単純な HTTP 要求で呼び出すことができます。受信要求を受け取ると、関数は context オブジェクトで最初のパラメーターとして呼び出されます。

6.6.3.1. Typescript コンテキストオブジェクト

関数を呼び出すには、context オブジェクトを最初のパラメーターとして指定します。context オブジェクトのプロパティーにアクセスすると、着信 HTTP 要求に関する情報を提供できます。

コンテキストオブジェクトの例

function handle(context:Context): string

この情報には、HTTP リクエストメソッド、リクエストと共に送信されたクエリー文字列またはヘッダー、HTTP バージョン、およびリクエスト本文が含まれます。CloudEvent の受信インスタンスが含まれる受信要求はコンテキストオブジェクトにアタッチし、context.cloudevent を使用してアクセスできるようにします。

6.6.3.1.1. コンテキストオブジェクトメソッド

context オブジェクトには、データの値を受け入れ、CloudEvent を返す cloudEventResponse() メソッドが 1 つあります。

Knative システムでは、サービスとしてデプロイされた関数が CloudEvent を送信するイベントブローカーによって呼び出される場合に、ブローカーが応答を確認します。応答が CloudEvent の場合には、このイベントはブローカーにが処理します。

コンテキストオブジェクトメソッドの例

// Expects to receive a CloudEvent with customer data
export function handle(context: Context, cloudevent?: CloudEvent): CloudEvent {
  // process the customer
  const customer = cloudevent.data;
  const processed = processCustomer(customer);
  return context.cloudEventResponse(customer)
    .source('/customer/process')
    .type('customer.processed')
    .response();
}

6.6.3.1.2. コンテキストタイプ

TypeScript タイプの定義ファイルは、関数で使用する以下のタイプをエクスポートします。

エクスポートタイプの定義

// Invokable is the expeted Function signature for user functions
export interface Invokable {
    (context: Context, cloudevent?: CloudEvent): any
}

// Logger can be used for structural logging to the console
export interface Logger {
  debug: (msg: any) => void,
  info:  (msg: any) => void,
  warn:  (msg: any) => void,
  error: (msg: any) => void,
  fatal: (msg: any) => void,
  trace: (msg: any) => void,
}

// Context represents the function invocation context, and provides
// access to the event itself as well as raw HTTP objects.
export interface Context {
    log: Logger;
    req: IncomingMessage;
    query?: Record<string, any>;
    body?: Record<string, any>|string;
    method: string;
    headers: IncomingHttpHeaders;
    httpVersion: string;
    httpVersionMajor: number;
    httpVersionMinor: number;
    cloudevent: CloudEvent;
    cloudEventResponse(data: string|object): CloudEventResponse;
}

// CloudEventResponse is a convenience class used to create
// CloudEvents on function returns
export interface CloudEventResponse {
    id(id: string): CloudEventResponse;
    source(source: string): CloudEventResponse;
    type(type: string): CloudEventResponse;
    version(version: string): CloudEventResponse;
    response(): CloudEvent;
}

6.6.3.1.3. CloudEvent data

受信要求が CloudEvent の場合は、CloudEvent に関連付けられたデータがすべてイベントから抽出され、2 番目のパラメーターとして提供されます。たとえば、以下のように data プロパティーに JSON 文字列が含まれる CloudEvent が受信された場合に、以下のようになります。

{
  "customerId": "0123456",
  "productId": "6543210"
}

呼び出されると、関数に対して context オブジェクト後に来る 2 番目のパラメーターは、JavaScript オブジェクトで、このオブジェクトには customerIdproductId プロパティーが含まれます。

署名の例

function handle(context: Context, cloudevent?: CloudEvent): CloudEvent

この例の cloudevent パラメーターは、customerId および productId プロパティーが含まれる JavaScript オブジェクトです。

6.6.4. Typescript 関数の戻り値

この関数は有効な JavaScript タイプを返すことができます。がそれ以外は戻り値を持たせないようにすることもできます。関数に戻り値が指定されておらず、失敗を指定しないと、呼び出し元は 204 No Content 応答を受け取ります。

関数は、CloudEvent または Message オブジェクトを返してイベントを Knative Eventing システムにプッシュすることもできます。この場合に、開発者は CloudEvent メッセージング仕様の理解や実装は必要ありません。返された値からのヘッダーおよびその他の関連情報は抽出され、応答で送信されます。

export const handle: Invokable = function (
  context: Context,
  cloudevent?: CloudEvent
): Message {
  // process customer and return a new CloudEvent
  const customer = cloudevent.data;
  return HTTP.binary(
    new CloudEvent({
      source: 'customer.processor',
      type: 'customer.processed'
    })
  );
};

6.6.4.1. 返されるヘッダー

headers プロパティーを return オブジェクトに追加して応答ヘッダーを設定できます。これらのヘッダーは抽出され、呼び出し元に応答して送信されます。

応答ヘッダーの例

export function handle(context: Context, cloudevent?: CloudEvent): Record<string, any> {
  // process customer and return custom headers
  const customer = cloudevent.data as Record<string, any>;
  return { headers: { 'customer-id': customer.id } };
}

6.6.4.2. 返されるステータスコード

statusCode プロパティーを return オブジェクトに追加して、呼び出し元に返されるステータスコードを設定できます。

ステータスコード

export function handle(context: Context, cloudevent?: CloudEvent): Record<string, any> {
  // process customer
  const customer = cloudevent.data as Record<string, any>;
  if (customer.restricted) {
    return {
      statusCode: 451
    }
  }
  // business logic, then
  return {
    statusCode: 240
  }
}

ステータスコードは、関数で作成および出力されるエラーに対して設定することもできます。

エラーステータスコードの例

export function handle(context: Context, cloudevent?: CloudEvent): Record<string, string> {
  // process customer
  const customer = cloudevent.data as Record<string, any>;
  if (customer.restricted) {
    const err = new Error(‘Unavailable for legal reasons’);
    err.statusCode = 451;
    throw err;
  }
}

6.6.5. TypeScript 関数のテスト

Typescript 機能は、お使いのコンピューターでローカルでテストできます。kn func create を使用した関数の作成時に作成される default プロジェクトには、test フォルダーがあり、一部の単純なユニットおよび統合テストが含まれます。

前提条件

  • OpenShift Serverless Operator および Knative Serving がクラスターにインストールされている。
  • Knative (kn) CLI をインストールしている。
  • kn func create を使用して関数を作成している。

手順

  1. テストを実行していない場合は、最初に依存関係をインストールします。

    $ npm install
  2. 関数の test フォルダーに移動します。
  3. テストを実行します。

    $ npm test

6.6.6. 次のステップ