【未公開記事の発掘】AWS Lambda ファンクションのインスタンスをウォームアップ状態で維持したい

起動に時間のかかるファンクションで困っていたのかもしれない。


背景

  • HTTP リクエストを処理するだけの Lambda ファンクションがある
  • ほとんどリクエストがこないのでそのたびに新規作成してる
  • リクエストの送信元が設定している応答タイムアウト時間が短くて、エラーになりやすい

目的

  • リクエストの送信元でタイムアウトしないようにしたい
  • リクエストのたびに新規作成しないで済むよう Lambda ファンクションを WarmUp 状態で維持する
  • できるだけ費用がかからないようにする

世の中の知見

ソリューション

Lambda ファンクションのインスタンスVPC で実行するなら15分、そうでないなら5分くらいで廃棄されるようです。

廃棄までの時間内に新しいイベントが到着すれば、継続して動き続けるはず。

できるだけ費用がかからないように、という前提があっても、定期的にリクエストを送信する方法はいろいろ考えられます。

第7回 Data-Oriented Programming 読書会


参加者トピック

  • 引き続き chatGPT 話題
    • 最近は Edge で Bing AI を使うことが増えている
    • ライブラリの選定に使っている人がいたりする
  • ステージマネージャ は便利なのでお勧め
  • Anker が古くなったモバイルバッテリーを引き取るキャンペーンをしている

nextbook

ディスカッション

13.4 Multimethods with dynamic dispatch

  • 実行時のデータに基づいて呼び出す関数を決める仕組みのことだった
  • 汎用データ構造でも静的型付け言語と同じようなことができる、ということなのかな

13.5 Integrating multimethods in a production system

  • 普通はプレゼンテーションに近いところで書式を指定するものだけど、モデルのすぐそばで判断、加工しているのは不思議

13 Summary

14 Advanced data manipulation

14.1 Updating a value in a map with eloquence

  • データを取得して加工して設定するのではなく、データを加工する関数を渡すようにする

14.2 Manipulating nested data

  • flatMapflatten + map のどちらが分かりやすいか議論している

14.3 Using the best tool for the job

  • forEach を撲滅したい

14.4 Unwinding at ease

  • MongoDB の $unwind オペレータは便利

14 Summary

15 Debugging

15.1 Determinism in programming

  • いろんな層の言葉が乱用されているし、基本的な事実を新発見のように説明しているので、読んでいてつらい
  • 経験主義というやつだろうか

15.2 Reproducibility with numbers and strings

15.3 Reproducibility with any data

15.4 Unit tests

15.5 Dealing with external data sources

15 Summary

参考情報

第6回 Data-Oriented Programming 読書会


参加者トピック

  • chatGPT の話ばかりしてる
  • GitHub CopilotOSS メンテナ認定は雑すぎて助かる
  • GPU ボードのメモリは 16 GB ないと厳しい

ディスカッション

11.3 Representing a client request as a map

  • 最初から汎用的なAPIにするのは早すぎる最適化だと思う

11.4 Representing a server response as a map

  • properties にフィールド名を書かなくても required に書いただけでフィールドを生やすらしい

11.5 Passing information forward

特になし

11.6 Search result enrichment in action

特になし

11 Summary

特になし

Part 3. Maintainability

特になし

12 Advanced data validation

特になし

12.1 Function arguments validation

  • 保守を任されたシステムで、最初の仕事がデータの型付けだったら辛すぎる
  • JSON Schema に静的型付け言語と同じような表現力を求めている

12.2 Return value validation

特になし

12.3 Advanced data validation

  • LOCALE=C date の出力を見ると format="date" が受け入れてもらえる気がしない
  • 不安なので正規表現を書いてしまう、と思う

12.4 Automatic generation of data model diagrams

PlantText UML Editor

12.5 Automatic generation of schema-based unit tests

12.6 A new gift

  • JSON Schema はフィールドの値域が条件によって変わるようだと記述量が多くなりがちで困る

12 Summary

  • OpenAPI は JSON Schema のスーパーセットでありサブセットでもあるので OpenAPI を使っていくとよさそう

13 Polymorphism

13.1 The essence of polymorphism

13.2 Multimethods with single dispatch

13.3 Multimethods with multiple dispatch

PlayCode - Javascript Playground

参考情報

第5回 Data-Oriented Programming 読書会


参加者トピック

ディスカッション

9 Persistent data structures

9.1 The need for persistent data structures

https://lampwww.epfl.ch/papers/idealhashtrees.pdf

9.2 The efficiency of persistent data structures

リストやツリーなど基本的なデータ構造が効率的だということを説明していた

9.3 Persistent data structures libraries

Clojure の提供するデータ構造、データ操作を、他のプログラミング言語でもライブラリとして利用できるようになっていることを説明していた

9.4 Persistent data structures in action

Lodash の _Immutable へ置き換えるだけで元のコードはほとんどそのまま動く

9. Summary

  • 不変コレクション永続化データ構造 は違う概念
  • 構造化共有が利用できると、元の値を破壊しないで効率的に新しい値を作ることができる

10 Database operations

10.1 Fetching data from the database

  • 普通は 遅延バインディング と言えば実行時に呼び出す関数を解決することを指す
    • このセクションでは、未知の値を既知の型として解釈することを指している
  • クエリごとに JSON Schema を書いてデータ型を検証する

10.2 Storing data in the database

  • 例えば Java では Map コレクションの要素にアクセスするとき map.item1 のようなドット記法は使えない
  • だから DOP の考え方を説明するときは汎用的な記法にする
    • 例えば Lodash なら _at(map, ["item1"]) と書ける

10.3 Simple data manipulation

  • データストアに保存し、取得できるフィールド名と、アプリケーションの使用したいフィールド名は異なる場合があるから、アプリケーション側で対応表を用意して、変換すればいいということを説明していた
    • 前のセクションで木構造を探索するCPU時間を気にしていたのに、突然富豪的な処理を導入しているのは不思議

10.4 Advanced data manipulation

  • SQL レベルでデータを操作している意味がわからない
    • システムの扱うすべてのデータはメモリ上に木構造で展開されていたはず
    • 差分を計算してアトミックに更新できるのではなかったのか

11 Web services

  • 10章データベース操作と同じく、アプリケーションの関心事だけを扱っている雰囲気

11.1 Another feature request

11.2 Building the insides like the outsides

参考情報

西暦1999年に好きだった音源を探してる

タイトルもアーティストもレーベルも覚えてないんだけど、頭の中でずっとループ再生できるくらい好きな音源がある。

高専に在学中の1995年から1999年の間にアナログレコードで購入して、もう手元には残ってない。

YouTube で音源を探すのは諦めていたけど、最近になってからSpotifyで探す意欲が湧いたので、覚えてるワードで検索したり、アーティストページのalso likeをさまよっている。

だんだん近づいてるはずだけど、最近は同じところに戻ることが増えていて発見がない。

第4回 Data-Oriented Programming 読書会


参加者トピック

ディスカッション

6.3 Unit tests for queries

文字列で比較するのをやめて、デシリアライズしたデータを比較する

6.4 Unit tests for mutations

ラッパー関数が多いときは末端の関数からテストを作る

Chapter 6. Moving Forward (ストーリーパート)

  • テオは開発がスケールしないという理由でDOPを採用しないつもりになっている
  • ジョーはそれを引き留めるため、オフィスで会話することにした

Part 2. Scalability (ストーリーパート)

  • DOPで作り直したプロトタイプには課題がある
    • 汎用的なデータ構造のため、開発者が増えると困ってしまう
    • 同時実行制御はスレッド安全ではない
    • structural sharingの仕組みはデータが複雑になると性能が悪くなる
  • どの課題もDOPを採用する妨げにはならない
  • DOPの理解を深めるために次のレッスンを始めよう

7.1 Data validation in DOP

  • データ表現とデータスキーマを分離する
  • システム境界を越えるデータの検証
    • システム内部で予期せぬデータが生まれてしまう可能性が減る
  • システム内部のデータの検証
    • コードベースが大きくなってもコーディングが容易になる

7.2 JSON Schema in a nutshell

JSONスキーマ

7.3 Schema flexibility and strictness

(感想)データ表現とデータスキーマを分けるという考え方は、同期や共有、後方互換性を保証するためのコストがかかるので、メリットよりデメリットが上回りそう

ロバストネス原則 - Wikipedia

7.4 Schema composition

anyOfallOf は便利そう

7.5 Details about data validation failures

Ajv JSON schema validator

7. Summary

  • システム境界でデータを検証し、境界の内側におかしなデータが入ってこないようにする
  • 開発環境ではシステム協会の内側でもデータを検証する
    • 名前の間違いを見つけたりできるので、開発の役に立つ

8 Advanced concurrency control

  • アトム というロックフリーな仕組みで並行処理を制御する
    • デッドロックを回避するために必要なロックの通常の複雑さは、アトムには適用されない

8.1 The complexity of locks

  • 不変データなら、読み取り中に他のスレッドが書き込みしても、一貫性は保たれる

8.2 Thread-safe counter with atoms

  • mutex を隠しているだけで特にいいことはなさそう
    • 解放忘れを避けられるし、CAS操作はCPUレベルの命令なので安心

8.3 Thread-safe cache with atoms

突然インメモリーキャッシュの話題になっていてよく分からない

8.4 State management with atoms

  • メッセージキューで操作を直列化するやり方に対するメリットは?
    • 扱うデータが複雑でも性能が劣化しないように思われる

8. Summary

参考情報

JUnitテストからtestcontainersで起動したDockerコンテナへの接続情報を環境変数で指定する

目的

  • 未公開記事の発掘
  • これ少し役に立った記憶がある
  • testcontainersで起動したRDBの接続情報を起動時に調整するなどした

前提

  • Java (Kotlin) プロジェクト
  • ビルドツールは Gradle
  • テストコードで testcontainers-java を使ってる

課題

解決方法

ファイルレイアウトはこういう感じになります。

./build.gradle
./settings.gradle
./src/main/java/xxxx
./src/test/java/xxxx
./.env

.env ファイルの内容は次のような感じです。

DOCKER_CERT_PATH=C:/Users/path/to/docker/certs
DOCKER_TLS_VERIFY=1
DOCKER_HOST=tcp://dockerhost:2376

最終的な build.gradle は次のような感じになります。

plugins {
    id 'java'
    id 'co.uzzu.dotenv.gradle' version '1.1.0' // プラグインの追加
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
}

dependencies {
    testImplementation('org.junit.jupiter:junit-jupiter-api:5.3.1')
    testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.3.1')
    testImplementation('org.testcontainers:junit-jupiter:1.14.3')
    testImplementation('org.testcontainers:postgresql:1.14.3')
}

test {
    useJUnitPlatform()
    // environment で指定した環境変数だけになるので、System.getenv() も指定しないとおかしなことになる
    environment = System.getenv() + [
        'DOCKER_HOST'      : env.fetch('DOCKER_HOST', 'unix:///var/run/docker.sock'),
        'DOCKER_TLS_VERIFY': env.fetch('DOCKER_TLS_VERIFY', ''),
        'DOCKER_CERT_PATH' : env.fetch('DOCKER_CERT_PATH', ''),
    ]
}