プロジェクトキャッシュ
Project Cache APIはAPI操作のためのインメモリプロジェクト読み込みを管理します。いつプロジェクトを読み込む必要があるかを理解することは、効率的なAPI利用に不可欠です。
主要概念
統一されたキャッシュアーキテクチャ
APIとUIは同じインメモリキャッシュを共有しています。API経由でプロジェクトを読み込むと、それはUIが利用するのと同じキャッシュです。これにより:
- 共有状態:API操作はUIユーザーと同じデータを参照
- 共有結果:実行結果はAPIとUIの両方に見える
- 不整合なし:APIとUIでプロジェクトの見え方が異なることは不可能
操作のカテゴリ
API操作はキャッシュ要件の異なる3つのカテゴリに分けられます:
| カテゴリ | 説明 | プロジェクトの読み込み必要? | 例 |
|---|---|---|---|
| 直接DB | 読み取り専用操作 | いいえ | GETエンドポイント、テナント/ユーザ管理 |
| 自動読み込み | 変更操作 | いいえ(自動読み込み) | 調査、ノートブック、ブロックのPOST/PUT/DELETE |
| 読み込み必要 | 実行操作 | はい | ノートブックの実行、実行結果の取得 |
自動読み込みパターン(簡易ワークフロー)
多くのCRUD操作では、明示的にプロジェクトを読み込む必要はありません。APIが必要に応じて自動でプロジェクトを読み込みます:
# 旧ワークフロー(CRUDでは不要になりました):
# manager.load_project(project_id) # 不要!
# 新ワークフロー - 直接操作を呼び出すだけ:
response = requests.put(
f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/notebook/{notebook_id}",
json={"Name": "Updated Name"},
headers=headers
)
# 必要ならプロジェクトが自動的に読み込まれます
明示的な読み込みが必要な場合
明示的なプロジェクトの読み込みは実行操作の場合のみ必要です:
POST /execution/notebook/{notebookId}- ノートブックを実行GET /execution/notebook/{notebookId}/results- 実行結果を取得GET /execution/status/{notebookId}- 実行ステータス確認
プロジェクトをキャッシュに読み込む
GET /api/{tenantId}/project/{projectId}/load
共有キャッシュにプロジェクトを読み込みます。ノートブック実行前に使用してください。
パスパラメータ
| パラメータ | 種別 | 必須 | 説明 |
|---|---|---|---|
tenantId |
GUID | はい | テナント識別子 |
projectId |
GUID | はい | プロジェクト識別子 |
レスポンス (200 OK)
{
"projectId": "87654321-4321-4321-4321-210987654321",
"projectName": "Purchase Order Analysis",
"tenantName": "acme-corp",
"investigationCount": 5,
"notebookCount": 12,
"datasetCount": 3,
"loadedFromCache": false,
"message": "Project loaded from database"
}
レスポンスフィールド
| フィールド | 種別 | 説明 |
|---|---|---|
projectId |
GUID | プロジェクト識別子 |
projectName |
string | プロジェクト名 |
tenantName |
string | テナント名 |
investigationCount |
integer | 調査件数 |
notebookCount |
integer | ノートブック数 |
datasetCount |
integer | データセット数 |
loadedFromCache |
boolean | 既にキャッシュにあればtrue、DBから読み込んだ場合はfalse |
message |
string | 読み込み状況の人間可読メッセージ |
キャッシュの動作
| シナリオ | レスポンス | パフォーマンス |
|---|---|---|
| 初回呼び出し(キャッシュミス) | loadedFromCache: false |
約1000ms(DBクエリ) |
| 2回目以降(キャッシュヒット) | loadedFromCache: true |
約75ms(13倍高速) |
| 30分間操作なし後 | キャッシュ期限切れ | 次回呼び出しで再読み込み |
キャッシュの特性
- 期間:最終アクセスから30分後に期限切れ
- 自動更新:プロジェクトへのAPI呼び出しがあるたびに30分タイマーリセット
- 共有:UIとAPIで同じキャッシュを使用
- メモリ管理:メモリ使用率90%で自動クリーンアップ
プロジェクトをキャッシュからアンロード
DELETE /api/{tenantId}/project/{projectId}/unload
キャッシュからプロジェクトを削除し、メモリを解放します。
パスパラメータ
| パラメータ | 種別 | 必須 | 説明 |
|---|---|---|---|
tenantId |
GUID | はい | テナント識別子 |
projectId |
GUID | はい | プロジェクト識別子 |
レスポンス (200 OK)
{
"projectId": "87654321-4321-4321-4321-210987654321",
"wasInCache": true,
"message": "Project unloaded from cache successfully"
}
ワークフロー例
ワークフローA: CRUD操作(自動読み込み)
調査、ノートブック、ブロックの作成・更新・削除の場合:
import requests
headers = {"Authorization": f"Bearer {API_KEY}"}
# 直接操作を呼び出すだけ - 明示的読み込み不要!
response = requests.post(
f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/investigation",
json={"name": "New Investigation", "description": "Created via API"},
headers=headers
)
# 必要ならプロジェクトが自動で読み込まれます
ワークフローB: ノートブック実行(読み込みが必要)
ノートブックの実行および結果取得の場合:
import requests
import time
headers = {"Authorization": f"Bearer {API_KEY}"}
# ステップ1: プロジェクト読み込み(実行に必須)
response = requests.get(
f"{BASE_URL}/api/{TENANT_ID}/project/{PROJECT_ID}/load",
headers=headers
)
print(f"プロジェクト読み込み完了: {response.json()['projectName']}")
# ステップ2: ノートブック実行
response = requests.post(
f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/execution/notebook/{NOTEBOOK_ID}",
headers=headers
)
print(f"実行キューに追加されました: {response.json()['status']}")
# ステップ3: 完了までポーリング
while True:
response = requests.get(
f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/execution/status/{NOTEBOOK_ID}",
headers=headers
)
status = response.json()
print(f"ステータス: {status['status']} ({status['progress']}%)")
if status['status'] == 'Completed':
break
time.sleep(2)
# ステップ4: 結果取得
response = requests.get(
f"{BASE_URL}/api/{TENANT_ID}/{PROJECT_ID}/execution/notebook/{NOTEBOOK_ID}/results",
headers=headers
)
results = response.json()
# ステップ5: プロジェクトアンロード(任意のクリーンアップ)
requests.delete(
f"{BASE_URL}/api/{TENANT_ID}/project/{PROJECT_ID}/unload",
headers=headers
)
実装例
cURL
# プロジェクトをキャッシュに読み込む
curl -X GET "https://your-mindzie-instance.com/api/12345678-1234-1234-1234-123456789012/project/87654321-4321-4321-4321-210987654321/load" \
-H "Authorization: Bearer YOUR_API_KEY"
# プロジェクトをキャッシュからアンロード
curl -X DELETE "https://your-mindzie-instance.com/api/12345678-1234-1234-1234-123456789012/project/87654321-4321-4321-4321-210987654321/unload" \
-H "Authorization: Bearer YOUR_API_KEY"
Python
import requests
TENANT_ID = '12345678-1234-1234-1234-123456789012'
BASE_URL = 'https://your-mindzie-instance.com'
class ProjectCacheManager:
def __init__(self, token):
self.headers = {
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json'
}
self.loaded_projects = set()
def load_project(self, project_id):
"""プロジェクトをキャッシュに読み込む(実行操作に必須)。"""
url = f'{BASE_URL}/api/{TENANT_ID}/project/{project_id}/load'
response = requests.get(url, headers=self.headers)
response.raise_for_status()
result = response.json()
self.loaded_projects.add(project_id)
status = "キャッシュから" if result['loadedFromCache'] else "データベースから"
print(f"プロジェクト '{result['projectName']}' を{status}読み込みました")
return result
def unload_project(self, project_id):
"""キャッシュからプロジェクトをアンロードする。"""
url = f'{BASE_URL}/api/{TENANT_ID}/project/{project_id}/unload'
response = requests.delete(url, headers=self.headers)
response.raise_for_status()
self.loaded_projects.discard(project_id)
return response.json()
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
for project_id in list(self.loaded_projects):
self.unload_project(project_id)
# コンテキストマネージャーでの使用例
with ProjectCacheManager('your-api-key') as cache:
result = cache.load_project('87654321-4321-4321-4321-210987654321')
# ここでノートブックを実行 ...
# ブロジェクトは自動でアンロードされます
JavaScript/Node.js
const TENANT_ID = '12345678-1234-1234-1234-123456789012';
const BASE_URL = 'https://your-mindzie-instance.com';
class ProjectCacheManager {
constructor(token) {
this.headers = {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
};
this.loadedProjects = new Set();
}
async loadProject(projectId) {
const url = `${BASE_URL}/api/${TENANT_ID}/project/${projectId}/load`;
const response = await fetch(url, { headers: this.headers });
if (!response.ok) throw new Error(`Failed: ${response.status}`);
const result = await response.json();
this.loadedProjects.add(projectId);
console.log(`読み込み完了: ${result.projectName} (キャッシュから:${result.loadedFromCache})`);
return result;
}
async unloadProject(projectId) {
const url = `${BASE_URL}/api/${TENANT_ID}/project/${projectId}/unload`;
const response = await fetch(url, {
method: 'DELETE',
headers: this.headers
});
this.loadedProjects.delete(projectId);
return response.json();
}
async unloadAll() {
await Promise.all(
Array.from(this.loadedProjects).map(id => this.unloadProject(id))
);
}
}
// 使用例
const cache = new ProjectCacheManager('your-api-key');
try {
await cache.loadProject('87654321-4321-4321-4321-210987654321');
// ここでノートブックを実行 ...
} finally {
await cache.unloadAll();
}
ベストプラクティス
- CRUD操作:明示的に読み込まず、自動読み込みに任せる
- 実行操作:必ず先にプロジェクトを読み込む
- 長時間稼働クライアント:完了時にプロジェクトをアンロードしてメモリを開放
- コンテキストマネージャー:Pythonの
withやtry/finallyでクリーンアップを行う - メモリ管理意識:キャッシュは90%メモリ使用時に自動クリーンアップされるが、明示的なアンロードが望ましい
- 共有キャッシュ:UIユーザーもAPI操作と同じプロジェクト状態を参照していることを意識すること