特徴量エンジンKaskadaリファレンス〜スペックファイル

# はじめに

先日、以下の記事を発表しました。

https://qiita.com/yoshiyuki_kono/items/7dc7bdad5e02ff986f5d

新しいテクノロジーに触れる時はいつでも楽しいものです。

まだまだ勉強中ですが、公式ドキュメントの学習過程の記録として、以下の記事をまとめてみました。

本稿情報のソースとして、下記ドキュメントを参照ください。

https://kaskada.io/docs-site/kaskada/main/developing/specFiles.html

また、本記事の前提となるKaskadaの基本構成について、以下を参照ください。

https://qiita.com/yoshiyuki_kono/items/0174944438d2280dc393

# スペックファイル
リソースを直接変更するだけでなく、仕様ファイルを使用してKaskada の望ましい状態を記述することもできます。

スペック ファイルは、テーブル、ビュー、マテリアライゼーションなどの Kaskada リソースのセットを記述する YAML ファイルです。

`sync`コマンドによって、仕様ファイル内のリソースの説明と一致するように Kaskada システムの状態を更新することができます。


## スペックファイル形式
スペック ファイルには、次のキーのいずれかを含めることができます: 
 - tables
 - views
 - materializations
 
各キーには、作成または更新されるリソースを記述するオブジェクトのリストが含まれています。

## テーブル
テーブルは、`tables`キーの下にテーブル オブジェクトのリストとして仕様ファイルに記述されます。

```yaml
tables:
  # The name of the table
- tableName: GamePlay
  # A field containing the time associated with each event
  timeColumnName: event_at
  # An initial entity key associated with each event
  entityKeyColumnName: entity_key
  # An (optional) subsort column associated with each event
  subsortColumnName: offset
  # A name describing the entity key
  groupingId: User
  # Where the table's data will be stored
  # The default storage location is 'kaskada', and uses local files to store events.
  source:
    kaskada: {}

  # The name of the table
- tableName: Purchase
  # A field containing the time associated with each event
  timeColumnName: event_at
  # An initial entity key associated with each event
  entityKeyColumnName: entity_id
  # A name describing the entity key
  groupingId: User
  # Where the table's data will be stored
  # The default storage location is 'kaskada', and uses local files to store events.
  source:
    kaskada: {}
```

## ビュー
ビューは、`views`キーの下にあるビュー オブジェクトのリストとして仕様ファイルに記述されます。

```yaml
views:
  # A name used to refer to the view in queries
- view_name: PurchaseStats
  # The expression to substitute anywhere the view's name is used
  expression: |
    {
        time: Purchase.purchase_time,
        entity: Purchase.customer_id,
        max_amount: Purchase.amount | max(),
        min_amount: Purchase.amount | min(),
        count: CountPurchase,
    }

  # A name used to refer to the view in queries
- view_name: CountPurchase
  # The expression to substitute anywhere the view's name is used
  expression: count(Purchase)
```

## マテリアライゼーション
マテリアライゼーションは、`materializations`キーの下にマテリアライゼーション オブジェクトのリストとして仕様ファイルに記述されます。

```yaml
materializations:
- materializationName: PurchaseStats
  expression: |
    {
        time: Purchase.purchase_time,
        entity: Purchase.customer_id,
        max_amount: Purchase.amount | max(),
        min_amount: Purchase.amount | min(),
        count: CountPurchase,
    }
  destination:
    objectStore:
      fileType: FILE_TYPE_PARQUET
      outputPrefixUri: s3://my-bucket/materialization-output-prefix/
  slice: {}
```

## エクスポート

 `export --all`フラグを指定した`sync`コマンドを使用して、システムに現在定義されているすべてのリソースから仕様ファイルを作成できます。

CLI
```
kaskada-cli sync export --all
```
エクスポート結果の例を以下に示します。

```
tables:
- tableName: GamePlay
  timeColumnName: event_at
  entityKeyColumnName: entity_key
  subsortColumnName: offset
  groupingId: User
  source:
    kaskada: {}
- tableName: Purchase
  timeColumnName: event_at
  entityKeyColumnName: entity_id
  groupingId: User
  source:
    kaskada: {}
views:
- view_name: CountPurchase
  expression: count(Purchase)
materializations:
- materializationName: PurchaseStats
  expression: |
    {
        time: Purchase.purchase_time,
        entity: Purchase.customer_id,
        max_amount: Purchase.amount | max(),
        min_amount: Purchase.amount | min(),
        count: CountPurchase,
    }
  destination:
    objectStore:
      fileType: FILE_TYPE_PARQUET
      outputPrefixUri: s3://my-bucket/materialization-output-prefix/
  slice: {}
```

あるいは、エクスポートしたい特定のテーブル、ビュー、またはマテリアライゼーションがわかっている場合は、それを明示的に指定することもできます。


```
kaskada-cli sync export --table Purchase
kaskada-cli sync export --view CountPurchase
kaskada-cli sync export --materialization PurchaseStats
```


## スペックファイル設定反映

リソース (テーブル、ビュー、マテリアライゼーション) を更新するには、まずスペックファイル内のリソースを変更し、次に`spec plan`コマンドを使用してシステムに加えられる変更をプレビューします。実際に変更を加えるには、`spec apply`コマンドを使用します。

スペックファイルが更新されると、CLI はサーバーのすべてのリソースとスペックファイルで定義されているすべてのリソースを検査し、サーバーの状態を調整するために必要なアクションを実行します。仕様を適用すると、新しいリソースを作成したり、リソースを削除して再作成して更新したりできます。

スペックファイルからリソースを削除しても、システムからは削除されません。代わりに、標準の削除コマンド (テーブルの削除、ビューの削除、またはマテリアライゼーションの削除 ) を使用して、これらのリソースを削除する必要があります。

## テーブルの更新
テーブルは現在不変(immutable)です。CLI がテーブルを更新するときは、テーブルを削除して再作成します。この際、以前にテーブルにロードされたデータはすべて失われます。

### 変更のプレビュー
このコマンドを実行してもサーバーに変更は加えられませんが、指定されたスペックファイルを適用した場合に加えられる変更が出力されます。

```
kaskada-cli sync plan --file spec.yaml

# > 2:18PM INF starting plan
# > 2:18PM INF resource not found on system, will create it kind=*kaskadav1alpha.Table name=GamePlay
# > 2:18PM INF resource not found on system, will create it kind=*kaskadav1alpha.Table name=Purchase
# > 2:18PM INF Success!
```

### 変更の適用

このコマンドを実行すると、変更がサーバーに適用されます。

```
kaskada-cli sync apply --file spec.yaml

# > 2:25PM INF starting apply
# > 2:25PM INF resource not found on system, will create it kind=*kaskadav1alpha.Table name=GamePlay
# > 2:25PM INF resource not found on system, will create it kind=*kaskadav1alpha.Table name=Purchase
# > 2:25PM INF created resource with provided spec kind=*kaskadav1alpha.Table name=GamePlay
# > 2:25PM INF created resource with provided spec kind=*kaskadav1alpha.Table name=Purchase
# > 2:25PM INF Success!
```