mcpField
E
encore-go-infrastructure

encore-go-infrastructure

github.com/encoredevクラウド・DevOps30211 回インストール2 日前に更新
リポジトリ

encore-go-infrastructure について

Encore Go アプリケーションでパッケージレベルのリソースを使ってインフラを宣言するスキルです。データベース、Pub/Sub、Cron、オブジェクトストレージ、シークレット、設定を扱います。

主な機能

  1. 01パッケージレベルのインフラ宣言
  2. 02PostgreSQL データベースとマイグレーション
  3. 03Pub/Sub トピックとサブスクリプション
  4. 04Cron ジョブのスケジュール
  5. 05オブジェクトストレージと署名付き URL
  6. 06シークレットと設定値

活用シーン

  1. 01サービスのデータベースとマイグレーションを宣言する
  2. 02イベントを発行・受信する
  3. 03定期ジョブをスケジュールする
  4. 04ファイルストレージと署名付きアクセスを管理する

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/encoredev/skills --skill encore-go-infrastructure

インストール後、Claude Code で/encore-go-infrastructureを入力して読み込まれたか確認します。

詳細

Encore Go インフラストラクチャ宣言

手順

Encore Go は宣言型インフラストラクチャを使用します。リソースをパッケージレベルの変数として定義すると、Encore がプロビジョニングを処理します。

  • ローカル (encore run) - Encore は Docker 内でインフラストラクチャ (Postgres、Redis など) を実行します
  • 本番環境 - Encore Cloud 経由で AWS/GCP にデプロイするか、生成されたインフラストラクチャ設定を使用してセルフホストします
重要なルール

すべてのインフラストラクチャは、関数内ではなく、パッケージレベルで宣言する必要があります。

データベース (PostgreSQL)

package user

import "encore.dev/storage/sqldb"

// CORRECT: Package level
var db = sqldb.NewDatabase("userdb", sqldb.DatabaseConfig{
    Migrations: "./migrations",
})

// WRONG: Inside function
func setup() {
    db := sqldb.NewDatabase("userdb", sqldb.DatabaseConfig{...})
}
マイグレーション

migrations/ ディレクトリにマイグレーションを作成します。

user/
├── user.go
├── db.go
└── migrations/
    ├── 1_create_users.up.sql
    └── 2_add_email_index.up.sql

マイグレーションの命名: {number}_{description}.up.sql

Pub/Sub

トピック
package events

import "encore.dev/pubsub"

type OrderCreatedEvent struct {
    OrderID string `json:"order_id"`
    UserID  string `json:"user_id"`
    Total   int    `json:"total"`
}

// Package level declaration
var OrderCreated = pubsub.NewTopic[*OrderCreatedEvent]("order-created", pubsub.TopicConfig{
    DeliveryGuarantee: pubsub.AtLeastOnce,
})
発行
msgID, err := events.OrderCreated.Publish(ctx, &events.OrderCreatedEvent{
    OrderID: "123",
    UserID:  "user-456",
    Total:   9999,
})
サブスクリプション
package notifications

import (
    "context"
    "myapp/events"
    "encore.dev/pubsub"
)

var _ = pubsub.NewSubscription(events.OrderCreated, "send-confirmation-email",
    pubsub.SubscriptionConfig[*events.OrderCreatedEvent]{
        Handler: sendConfirmationEmail,
    },
)

func sendConfirmationEmail(ctx context.Context, event *events.OrderCreatedEvent) error {
    // Send email...
    return nil
}
トピック参照

静的解析を維持しながら、ライブラリコードにトピックアクセスを渡します。

// Create a reference with publish permission
ref := pubsub.TopicRef[pubsub.Publisher[*OrderCreatedEvent]](OrderCreated)

// Use the reference in library code
func publishEvent(ref pubsub.Publisher[*OrderCreatedEvent], event *OrderCreatedEvent) error {
    _, err := ref.Publish(ctx, event)
    return err
}

Cron ジョブ

package cleanup

import (
    "context"
    "encore.dev/cron"
)

// The cron job declaration
var _ = cron.NewJob("cleanup-sessions", cron.JobConfig{
    Title:    "Clean up expired sessions",
    Schedule: "0 * * * *",  // Every hour
    Endpoint: CleanupExpiredSessions,
})

//encore:api private
func CleanupExpiredSessions(ctx context.Context) error {
    // Cleanup logic
    return nil
}
スケジュール形式
形式例説明
Cron 式"0 9 * * 1"毎週月曜日の午前9時
インターバル"every 1h"1時間ごと
インターバル"every 30m"30分ごと

オブジェクトストレージ

package uploads

import "encore.dev/storage/objects"

// Package level
var Uploads = objects.NewBucket("user-uploads", objects.BucketConfig{})

// Public bucket
var PublicAssets = objects.NewBucket("public-assets", objects.BucketConfig{
    Public: true,
})
操作
// Upload (streaming pattern)
writer := Uploads.Upload(ctx, "path/to/file.jpg")
_, err := io.Copy(writer, dataReader)
if err != nil {
    writer.Abort()
    return err
}
err = writer.Close()

// Download
reader := Uploads.Download(ctx, "path/to/file.jpg")
if err := reader.Err(); err != nil {
    return err
}
defer reader.Close()
data, _ := io.ReadAll(reader)

// Check existence
exists, err := Uploads.Exists(ctx, "path/to/file.jpg")

// Get attributes (size, content type, ETag)
attrs, err := Uploads.Attrs(ctx, "path/to/file.jpg")

// List objects
for err, entry := range Uploads.List(ctx, &objects.Query{}) {
    if err != nil {
        return err
    }
    fmt.Println(entry.Key, entry.Size)
}

// Delete
err := Uploads.Remove(ctx, "path/to/file.jpg")

// Public URL (only for public buckets)
url := PublicAssets.PublicURL("image.jpg")
署名付き URL

バケットを公開せずにアップロード/ダウンロード用の一時的な URL を生成します。

import "time"

// Signed upload URL (expires in 2 hours)
url, err := Uploads.SignedUploadURL(ctx, "user-uploads/avatar.jpg",
    objects.WithTTL(time.Duration(7200)*time.Second))

// Signed download URL
url, err := Uploads.SignedDownloadURL(ctx, "documents/report.pdf",
    objects.WithTTL(time.Duration(7200)*time.Second))
バケット参照

特定の権限を持つバケットアクセスをライブラリコードに渡します。

// Create a reference with download permission only
ref := objects.BucketRef[objects.Downloader](Uploads)

// Create a reference with multiple permissions
type myPerms interface {
    objects.Downloader
    objects.Uploader
}
ref := objects.BucketRef[myPerms](Uploads)

// Permission types: Downloader, Uploader, Lister, Attrser, Remover,
// SignedDownloader, SignedUploader, ReadWriter

シークレット

package email

var secrets struct {
    SendGridAPIKey string
    SMTPPassword   string
}

func sendEmail() error {
    apiKey := secrets.SendGridAPIKey
    // Use the secret...
}

CLI 経由でシークレットを設定します。

encore secret set --type prod SendGridAPIKey

設定値

package myservice

import "encore.dev/config"

var cfg struct {
    MaxRetries config.Int
    BaseURL    config.String
    Debug      config.Bool
}

func doSomething() {
    if cfg.Debug() {
        log.Println("Debug mode enabled")
    }
}

ガイドライン

  • インフラストラクチャの宣言はパッケージレベルで行う必要があります
  • リソースには説明的な名前を使用してください
  • マイグレーションは連番で順序を保ってください
  • サブスクリプションハンドラーは冪等でなければなりません (少なくとも1回の配信)
  • シークレットは関数として呼び出すことでアクセスします
  • Cron エンドポイントは private (内部のみ) にする必要があります
  • 通常、各サービスは独自のデータベースを持ちます

コメント