Skip to content

Commit 6af9953

Browse files
authored
Merge pull request #37 from smalruby/fix/heartbeat-ttl-env-vars
fix: use MESH_HOST_HEARTBEAT_TTL_SECONDS environment variable
2 parents 8d2996b + 6fd3898 commit 6af9953

15 files changed

Lines changed: 66 additions & 27 deletions

CLAUDE.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,11 @@ Mesh v2 uses environment variables for configuration, allowing different setting
8888
| Variable | Development | Production | Description |
8989
|----------|-------------|------------|-------------|
9090
| `MESH_SECRET_KEY` | `dev-secret-key-for-testing` | (set in GitHub Secrets) | Secret key for domain validation |
91-
| `MESH_HOST_HEARTBEAT_INTERVAL_SECONDS` | `15` | `30` | Host heartbeat interval in seconds |
92-
| `MESH_HOST_HEARTBEAT_TTL_SECONDS` | `60` | `150` | Host group TTL in seconds (5× interval) |
91+
| `MESH_HOST_HEARTBEAT_INTERVAL_SECONDS` | `15` | `60` | Host heartbeat interval in seconds |
92+
| `MESH_HOST_HEARTBEAT_TTL_SECONDS` | `60` | `150` | Host group TTL in seconds |
9393
| `MESH_MEMBER_HEARTBEAT_INTERVAL_SECONDS` | `15` | `120` | Member heartbeat interval in seconds |
94-
| `MESH_MEMBER_HEARTBEAT_TTL_SECONDS` | `60` | `600` | Member node TTL in seconds (5× interval) |
95-
| `MESH_MAX_CONNECTION_TIME_MINUTES` | `10` | `50` | Maximum connection time for a group (minutes) |
94+
| `MESH_MEMBER_HEARTBEAT_TTL_SECONDS` | `60` | `600` | Member node TTL in seconds |
95+
| `MESH_MAX_CONNECTION_TIME_MINUTES` | `5` | `25` | Maximum connection time for a group (minutes) |
9696

9797
### Setup for Local Development
9898

@@ -118,7 +118,7 @@ npx cdk deploy --context stage=stg
118118

119119
**Command Line Override**:
120120
```bash
121-
MESH_HOST_HEARTBEAT_INTERVAL_SECONDS=30 \
121+
MESH_HOST_HEARTBEAT_INTERVAL_SECONDS=60 \
122122
MESH_MEMBER_HEARTBEAT_INTERVAL_SECONDS=120 \
123123
npx cdk deploy --context stage=prod
124124
```

docs/api-reference.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ mutation RenewHeartbeat($groupId: ID!, $domain: String!, $hostId: ID!) {
351351

352352
**重要**: この mutation はホストのみが実行できます。非ホストが実行すると `Unauthorized` エラーが返されます。
353353

354-
**ハートビート間隔**: 環境変数 `MESH_HOST_HEARTBEAT_INTERVAL_SECONDS` で設定(開発環境: 15秒、本番環境: 30秒
354+
**ハートビート間隔**: 環境変数 `MESH_HOST_HEARTBEAT_INTERVAL_SECONDS` で設定(開発環境: 15秒、本番環境: 60秒
355355

356356
---
357357

docs/deployment.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ cp .env.example .env
7474
| 変数名 | 開発環境推奨値 | 本番環境推奨値 | 説明 |
7575
|--------|--------------|--------------|------|
7676
| `MESH_SECRET_KEY` | `dev-secret-key-for-testing` | (GitHub Secretsで設定) | ドメイン検証用の秘密鍵 |
77-
| `MESH_HOST_HEARTBEAT_INTERVAL_SECONDS` | `15` | `30` | ホストのハートビート送信間隔(秒) |
77+
| `MESH_HOST_HEARTBEAT_INTERVAL_SECONDS` | `15` | `60` | ホストのハートビート送信間隔(秒) |
7878
| `MESH_HOST_HEARTBEAT_TTL_SECONDS` | `60` | `150` | ホストグループの有効期限(秒) |
7979
| `MESH_MEMBER_HEARTBEAT_INTERVAL_SECONDS` | `15` | `120` | メンバーのハートビート送信間隔(秒) |
8080
| `MESH_MEMBER_HEARTBEAT_TTL_SECONDS` | `60` | `600` | メンバーノードの有効期限(秒) |
81-
| `MESH_MAX_CONNECTION_TIME_SECONDS` | `300` | `3000` | グループの最大接続時間(秒) |
81+
| `MESH_MAX_CONNECTION_TIME_SECONDS` | `300` | `1500` | グループの最大接続時間(秒) |
8282

8383
### 3.3 開発環境用の設定(stg)
8484

@@ -101,11 +101,11 @@ MESH_MAX_CONNECTION_TIME_SECONDS=300
101101
```bash
102102
# 本番環境ではGitHub Secretsまたは環境変数で設定
103103
MESH_SECRET_KEY=<本番用の秘密鍵>
104-
MESH_HOST_HEARTBEAT_INTERVAL_SECONDS=30
104+
MESH_HOST_HEARTBEAT_INTERVAL_SECONDS=60
105105
MESH_HOST_HEARTBEAT_TTL_SECONDS=150
106106
MESH_MEMBER_HEARTBEAT_INTERVAL_SECONDS=120
107107
MESH_MEMBER_HEARTBEAT_TTL_SECONDS=600
108-
MESH_MAX_CONNECTION_TIME_SECONDS=3000
108+
MESH_MAX_CONNECTION_TIME_SECONDS=1500
109109
```
110110

111111
**重要**:
@@ -175,10 +175,11 @@ npx cdk deploy
175175
```bash
176176
# 環境変数を直接指定してデプロイ
177177
MESH_SECRET_KEY="<本番用秘密鍵>" \
178-
MESH_HOST_HEARTBEAT_INTERVAL_SECONDS=30 \
178+
MESH_HOST_HEARTBEAT_INTERVAL_SECONDS=60 \
179179
MESH_HOST_HEARTBEAT_TTL_SECONDS=150 \
180180
MESH_MEMBER_HEARTBEAT_INTERVAL_SECONDS=120 \
181181
MESH_MEMBER_HEARTBEAT_TTL_SECONDS=600 \
182+
MESH_MAX_CONNECTION_TIME_SECONDS=1500 \
182183
npx cdk deploy --context stage=prod
183184
```
184185

docs/development.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ Mesh v2 は環境変数を使用して設定を管理し、開発環境と本番
138138
**本番環境(遅い間隔)**:
139139
- コスト最適化(~70% のコスト削減)
140140
- メンバーのハートビート 120 秒により、UX を維持しつつ API 呼び出しを削減
141-
- ホストのハートビート 30 秒により、グループ解散の検出を迅速化
141+
- ホストのハートビート 60 秒により、グループ解散の検出を迅速化
142142
- TTL を間隔の 5 倍にすることで、ネットワークの一時的な問題に対応
143143

144144
### 環境変数の使用方法

js/functions/checkExistingGroup.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import { util } from '@aws-appsync/utils';
55

66
export function request(ctx) {
77
const { hostId, domain } = ctx.args;
8+
const nowEpoch = Math.floor(util.time.nowEpochMilliSeconds() / 1000);
9+
const ttlSeconds = +(ctx.env.MESH_HOST_HEARTBEAT_TTL_SECONDS || '150');
10+
const threshold = nowEpoch - ttlSeconds;
11+
const nowISO = util.time.nowISO8601();
812

913
// 既存グループの検索
1014
return {
@@ -17,9 +21,11 @@ export function request(ctx) {
1721
})
1822
},
1923
filter: {
20-
expression: 'hostId = :hostId',
24+
expression: 'hostId = :hostId AND heartbeatAt > :threshold AND expiresAt > :now',
2125
expressionValues: util.dynamodb.toMapValues({
22-
':hostId': hostId
26+
':hostId': hostId,
27+
':threshold': threshold,
28+
':now': nowISO
2329
})
2430
}
2531
};

js/functions/checkGroupExists.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ export function request(ctx) {
1919
export function response(ctx) {
2020
const { groupId, domain } = ctx.args;
2121
const nowEpoch = Math.floor(util.time.nowEpochMilliSeconds() / 1000);
22-
const heartbeatThreshold = nowEpoch - 60; // heartbeat閾値: 60秒
22+
const ttlSeconds = +(ctx.env.MESH_HOST_HEARTBEAT_TTL_SECONDS || '150');
23+
const heartbeatThreshold = nowEpoch - ttlSeconds;
2324

2425
// グループが存在しない
2526
if (!ctx.result) {

js/functions/createGroupIfNotExists.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export function request(ctx) {
2424
}
2525

2626
// maxConnectionTimeSeconds のバリデーションと決定
27-
const envMaxSeconds = +(ctx.env.MESH_MAX_CONNECTION_TIME_SECONDS || '3000');
27+
const envMaxSeconds = +(ctx.env.MESH_MAX_CONNECTION_TIME_SECONDS || '1500');
2828
let actualMaxSeconds = envMaxSeconds;
2929

3030
if (maxConnectionTimeSeconds !== undefined && maxConnectionTimeSeconds !== null) {
@@ -46,7 +46,8 @@ export function request(ctx) {
4646
const now = util.time.nowISO8601();
4747
const nowEpoch = Math.floor(util.time.nowEpochMilliSeconds() / 1000);
4848
const expiresAt = util.time.epochMilliSecondsToISO8601(util.time.nowEpochMilliSeconds() + actualMaxSeconds * 1000);
49-
const ttl = nowEpoch + 60; // 1分間
49+
const ttlSeconds = +(ctx.env.MESH_HOST_HEARTBEAT_TTL_SECONDS || '150');
50+
const ttl = nowEpoch + ttlSeconds;
5051

5152
return {
5253
operation: 'PutItem',

js/functions/findNodeMetadata.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ export function response(ctx) {
2020
util.error(ctx.error.message, ctx.error.type);
2121
}
2222

23-
if (!ctx.result) {
23+
const result = ctx.result;
24+
const nowEpoch = Math.floor(util.time.nowEpochMilliSeconds() / 1000);
25+
26+
if (!result || (result.ttl && result.ttl <= nowEpoch)) {
2427
return null;
2528
}
2629

2730
// stashに保存して次のFunctionへ
28-
ctx.stash.nodeMetadata = ctx.result;
29-
return ctx.result;
31+
ctx.stash.nodeMetadata = result;
32+
return result;
3033
}

js/functions/renewHeartbeatFunction.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,6 @@ export function response(ctx) {
4848
groupId: groupId,
4949
domain: domain,
5050
expiresAt: group.expiresAt,
51-
heartbeatIntervalSeconds: +(ctx.env.MESH_HOST_HEARTBEAT_INTERVAL_SECONDS || '30')
51+
heartbeatIntervalSeconds: +(ctx.env.MESH_HOST_HEARTBEAT_INTERVAL_SECONDS || '60')
5252
};
5353
}

js/resolvers/Mutation.createGroup.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export function request(ctx) {
1212
}
1313

1414
// maxConnectionTimeSeconds のバリデーションと決定
15-
const envMaxSeconds = +(ctx.env.MESH_MAX_CONNECTION_TIME_SECONDS || '3000');
15+
const envMaxSeconds = +(ctx.env.MESH_MAX_CONNECTION_TIME_SECONDS || '1500');
1616
let actualMaxSeconds = envMaxSeconds;
1717

1818
if (maxConnectionTimeSeconds !== undefined && maxConnectionTimeSeconds !== null) {
@@ -34,7 +34,8 @@ export function request(ctx) {
3434
const now = util.time.nowISO8601();
3535
const nowEpoch = Math.floor(util.time.nowEpochMilliSeconds() / 1000);
3636
const expiresAt = util.time.epochMilliSecondsToISO8601(util.time.nowEpochMilliSeconds() + actualMaxSeconds * 1000);
37-
const ttl = nowEpoch + 60; // 1分間
37+
const ttlSeconds = +(ctx.env.MESH_HOST_HEARTBEAT_TTL_SECONDS || '150');
38+
const ttl = nowEpoch + ttlSeconds;
3839

3940
return {
4041
operation: 'PutItem',

0 commit comments

Comments
 (0)