Docs/database-schema

データベーススキーマドキュメント

ReCoronのデータベース設計と各テーブルの詳細説明です。

📋 目次

概要

ReCoronはPrisma ORMを使用してPostgreSQLデータベースと連携しています。スキーマは以下の4つの主要カテゴリに分類されています:

  1. Enums - 基本的な型定義
  2. 認証関連 - Better Authによるユーザー管理
  3. コア機能 - ジョブとAPIキー管理
  4. 使用量追跡 - 課金と悪用防止

Enums(列挙型)

Plan(プラン)

ユーザーの料金プランを定義します。

説明ジョブ数月次実行回数最小実行間隔
FREE無料プラン5個500回60分
HOBBY趣味プラン20個10,000回30分
PROプロプラン100個50,000回15分

Method(HTTPメソッド)

HTTPリクエストのメソッドを定義します。

  • GET - リソースの取得
  • POST - リソースの作成
  • PUT - リソースの完全更新
  • DELETE - リソースの削除
  • PATCH - リソースの部分更新

Type(実行タイプ)

ジョブの実行方法を定義します。

説明
AUTO自動実行(スケジュールに基づく)
MANUAL手動実行(API経由)

認証関連モデル

User(ユーザー)

システムのユーザー情報を管理します。Better Authと連携しています。

フィールド

フィールド必須デフォルト説明
idString-ユーザーID(主キー)
nameString-ユーザー名
emailString-メールアドレス(一意)
emailVerifiedBooleanfalseメール認証済みフラグ
imageString?-nullプロフィール画像URL
planPlanFREE料金プラン
isAdminBooleanfalse管理者権限フラグ
createdAtDateTimenow()作成日時
updatedAtDateTimenow()更新日時

リレーション

  • sessions - ユーザーのセッション(1対多)
  • accounts - OAuth連携アカウント(1対多)
  • jobs - 作成したジョブ(1対多)
  • logs - 実行ログ(1対多)
  • apiKeys - APIキー(1対多)
  • monthlyUsages - 月次使用量(1対多)
  • dailyUsages - 日次使用量(1対多)
  • resourceHistories - リソース履歴(1対多)
  • WebhookJobs - Webhookジョブ(1対多)

インデックス

  • email - 一意制約

Session(セッション)

ユーザーの認証セッションを管理します。

フィールド

フィールド必須デフォルト説明
idString-セッションID(主キー)
tokenString-セッショントークン(一意)
expiresAtDateTime-有効期限
ipAddressString?-nullアクセス元IPアドレス
userAgentString?-nullユーザーエージェント
userIdString-ユーザーID(外部キー)
createdAtDateTimenow()作成日時
updatedAtDateTimenow()更新日時

リレーション

  • user - ユーザー(多対1、カスケード削除)

インデックス

  • token - 一意制約

Account(アカウント)

OAuth連携情報やパスワード認証を管理します。

フィールド

フィールド必須デフォルト説明
idString-アカウントID(主キー)
accountIdString-プロバイダー側のアカウントID
providerIdString-プロバイダーID(github, google等)
userIdString-ユーザーID(外部キー)
accessTokenString?-nullアクセストークン
refreshTokenString?-nullリフレッシュトークン
idTokenString?-nullIDトークン
accessTokenExpiresAtDateTime?-nullアクセストークン有効期限
refreshTokenExpiresAtDateTime?-nullリフレッシュトークン有効期限
scopeString?-nullスコープ
passwordString?-nullパスワードハッシュ
createdAtDateTimenow()作成日時
updatedAtDateTimenow()更新日時

リレーション

  • user - ユーザー(多対1、カスケード削除)

Verification(検証)

メール認証などの検証トークンを管理します。

フィールド

フィールド必須デフォルト説明
idString-検証ID(主キー)
identifierString-識別子(メールアドレス等)
valueString-検証トークン
expiresAtDateTime-有効期限
createdAtDateTimenow()作成日時
updatedAtDateTimenow()更新日時

コア機能モデル

Job(Cronジョブ)

スケジュール実行されるHTTPリクエストを管理します。

フィールド

フィールド必須デフォルト説明
idStringcuid()ジョブID(主キー)
userIdString-ユーザーID(外部キー)
nameString-ジョブ名
scheduleString-Cron式(例: "0 9 * * *")
timezoneString"Asia/Tokyo"タイムゾーン
urlString-リクエスト先URL
methodMethodGETHTTPメソッド
headersJson?-nullカスタムヘッダー
bodyString?-nullリクエストボディ
enabledBooleantrue有効/無効フラグ
lastRunAtDateTime?-null最終実行日時
nextRunAtDateTime?-null次回実行予定日時
countInt0実行回数
createdAtDateTimenow()作成日時
updatedAtDateTimenow()更新日時

リレーション

  • user - ユーザー(多対1、カスケード削除)
  • runningLogs - 実行ログ(1対多)
  • WebhookJobs - Webhookジョブ(1対1、オプション)

インデックス

  • userId - パフォーマンス向上
  • (enabled, nextRunAt) - 実行対象ジョブの検索用

使用例

// ジョブ作成
const job = await prisma.job.create({
  data: {
    userId: "user_123",
    name: "Daily Report",
    schedule: "0 9 * * *",
    timezone: "Asia/Tokyo",
    url: "https://api.example.com/report",
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ report: "daily" }),
  },
});

RunningLog(実行ログ)

ジョブの実行結果を記録します。

フィールド

フィールド必須デフォルト説明
idStringcuid()ログID(主キー)
jobIdString?-nullジョブID(外部キー、オプション)
userIdString-ユーザーID(外部キー)
typeTypeAUTO実行タイプ
startedAtDateTime-実行開始時刻
finishedAtDateTimenow()実行完了時刻
urlString-リクエストURL
statusInt-HTTPステータスコード
responseBodyString?-nullレスポンスボディ
responseHeadersJson?-nullレスポンスヘッダー
durationMsInt-実行時間(ミリ秒)
successfulBooleantrue成功/失敗フラグ
createdAtDateTimenow()作成日時

リレーション

  • job - ジョブ(多対1、NULL設定)
  • user - ユーザー(多対1、カスケード削除)

インデックス

  • jobId - ジョブごとのログ検索用
  • createdAt - 日時順のログ取得用

注意事項

  • jobIdは削除されたジョブの場合NULLになります
  • ユーザーが削除されるとログも削除されます

WebhookJobs(Webhookジョブ)

外部サービスからのHTTPリクエストを受け付けるジョブです。

フィールド

フィールド必須デフォルト説明
idStringcuid()WebhookジョブID(主キー)
userIdString-ユーザーID(外部キー)
jobIdString-ジョブID(外部キー、一意)
endpointString-Webhookエンドポイント
headersJson?-nullカスタムヘッダー
createdAtDateTimenow()作成日時
updatedAtDateTimenow()更新日時

リレーション

  • user - ユーザー(多対1、カスケード削除)
  • job - ジョブ(1対1、カスケード削除)

インデックス

  • userId - パフォーマンス向上
  • jobId - 一意制約

APIKey(APIキー)

プログラマティックアクセス用の認証キーを管理します。

フィールド

フィールド必須デフォルト説明
idStringcuid()APIキーID(主キー)
userIdString-ユーザーID(外部キー)
nameString-APIキー名(識別用)
keyHashString-トークンのハッシュ値(一意)
lastUsedDateTime?-null最終使用日時
expiresAtDateTime?-null有効期限
countInt0使用回数
scopesString[][]アクセススコープ
enabledBooleantrue有効/無効フラグ
createdAtDateTimenow()作成日時
updatedAtDateTimenow()更新日時

リレーション

  • user - ユーザー(多対1、カスケード削除)
  • logs - APIログ(1対多)

インデックス

  • userId - パフォーマンス向上
  • keyHash - トークン検証用(一意制約)

スコープ

APIキーには以下のスコープを設定できます:

スコープ説明
read:jobsジョブの読み取り
write:jobsジョブの作成・更新・削除
read:keysAPIキーの読み取り
write:keysAPIキーの作成・削除

セキュリティ

  • トークンはハッシュ化されて保存されます
  • 実際のトークンは作成時のみ表示されます
  • 有効期限を設定できます

APILog(APIログ)

APIキーを使用したリクエストの履歴を記録します。

フィールド

フィールド必須デフォルト説明
idStringcuid()ログID(主キー)
apiKeyIdString-APIキーID(外部キー)
urlString-リクエストURL
methodMethod-HTTPメソッド
requestHeadersJson?-nullリクエストヘッダー
requestBodyString?-nullリクエストボディ
createdAtDateTimenow()作成日時

リレーション

  • apiKey - APIキー(多対1、カスケード削除)

インデックス

  • apiKeyId - APIキーごとのログ検索用

使用量追跡モデル

MonthlyUsage(月次使用量)

ユーザーの月ごとの使用量と課金情報を追跡します。

フィールド

フィールド必須デフォルト説明
idStringcuid()使用量ID(主キー)
userIdString-ユーザーID(外部キー)
yearInt-
monthInt-月(1-12)
totalExecutionsInt0総ジョブ実行回数
totalApiCallsInt0総API呼び出し回数
billedAmountDecimal0課金額
paidBooleanfalse支払い済みフラグ
createdAtDateTimenow()作成日時
updatedAtDateTimenow()更新日時

リレーション

  • user - ユーザー(多対1、カスケード削除)

インデックス

  • (userId, year, month) - 一意制約
  • userId - パフォーマンス向上
  • (year, month) - 期間検索用

特徴

  • 削除されたリソースの使用量も含む
  • 悪用防止(頻繁な削除・再作成)に使用
  • 課金計算の基礎データ

DailyUsage(日次使用量)

より細かい粒度での使用量を追跡します。

フィールド

フィールド必須デフォルト説明
idStringcuid()使用量ID(主キー)
userIdString-ユーザーID(外部キー)
dateDate-日付
executionsInt0実行回数
apiCallsInt0API呼び出し回数
peakJobCountInt0最大ジョブ数
peakApiKeyCountInt0最大APIキー数
createdAtDateTimenow()作成日時
updatedAtDateTimenow()更新日時

リレーション

  • user - ユーザー(多対1、カスケード削除)

インデックス

  • (userId, date) - 一意制約
  • userId - パフォーマンス向上
  • date - 日付検索用

用途

  • 日次レポート生成
  • ピーク時の把握
  • より詳細な使用パターン分析

ResourceHistory(リソース履歴)

ジョブやAPIキーの作成・削除を追跡します。

フィールド

フィールド必須デフォルト説明
idStringcuid()履歴ID(主キー)
userIdString-ユーザーID(外部キー)
resourceTypeString-リソースタイプ("JOB" or "API_KEY")
resourceIdString-リソースID
actionString-アクション("CREATED" or "DELETED")
createdAtDateTimenow()作成日時

リレーション

  • user - ユーザー(多対1、カスケード削除)

インデックス

  • (userId, resourceType) - パフォーマンス向上
  • createdAt - 時系列検索用

悪用防止

このテーブルは以下の悪用を防ぐために使用されます:

// 例: 今日の作成・削除回数をチェック
const todayHistory = await prisma.resourceHistory.findMany({
  where: {
    userId: "user_123",
    resourceType: "JOB",
    createdAt: {
      gte: new Date(new Date().setHours(0, 0, 0, 0)),
    },
  },
});

const createdCount = todayHistory.filter(h => h.action === "CREATED").length;
const deletedCount = todayHistory.filter(h => h.action === "DELETED").length;

// 今日5回以上作成削除している場合は制限
if (createdCount + deletedCount >= 10) {
  throw new Error("今日の作成・削除回数の上限に達しました");
}

リレーションシップ図

User
├── Session (1:多)
├── Account (1:多)
├── Job (1:多)
│   ├── RunningLog (1:多)
│   └── WebhookJobs (1:1)
├── APIKey (1:多)
│   └── APILog (1:多)
├── MonthlyUsage (1:多)
├── DailyUsage (1:多)
└── ResourceHistory (1:多)

データベース操作のベストプラクティス

1. トランザクション

複数のテーブルを更新する場合はトランザクションを使用:

await prisma.$transaction([
  prisma.job.create({ /* ... */ }),
  prisma.resourceHistory.create({
    data: {
      userId: "user_123",
      resourceType: "JOB",
      resourceId: jobId,
      action: "CREATED",
    },
  }),
  prisma.dailyUsage.update({ /* ... */ }),
]);

2. インデックスの活用

頻繁に検索されるフィールドにはインデックスが設定されています:

// ✅ インデックスを活用(高速)
await prisma.job.findMany({
  where: {
    userId: "user_123",
    enabled: true,
  },
});

// ❌ インデックスを活用していない(低速)
await prisma.job.findMany({
  where: {
    name: { contains: "report" },
  },
});

3. カスケード削除

ユーザーを削除すると関連データも自動削除されます:

// ユーザー削除時に自動削除されるもの:
// - Session
// - Account
// - Job(→ RunningLog, WebhookJobsも削除)
// - APIKey(→ APILogも削除)
// - MonthlyUsage
// - DailyUsage
// - ResourceHistory
await prisma.user.delete({
  where: { id: "user_123" },
});

マイグレーション

マイグレーション作成

npx prisma migrate dev --name add_new_feature

マイグレーション適用

# 開発環境
npx prisma migrate dev

# 本番環境
npx prisma migrate deploy

Prisma Clientの再生成

スキーマ変更後は必ず実行:

npx prisma generate

参考リンク