0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Ninda 7日目: 名前付きスペース 〜複数スペースによる整理術〜

Posted at

今日のゴール

  • 名前付きスペースの概念と用途を理解する
  • 複数スペースを使ったアプリケーション設計を学ぶ
  • スペース間のデータ分離と整理術を身につける

なぜ複数のスペースが必要か

単一のタプルスペースでも多くの問題は解決できます。しかし、アプリケーションが大きくなると問題が発生します。

問題 名前付きスペースで解決
名前空間の衝突 スペースごとに独立
検索効率の低下 関連するタプルだけをスキャン
論理的な分離の欠如 責務ごとにスペースを分割

基本的な使い方

let manager = newSpaceManager()

# デフォルトスペース
let defaultSpace = manager.space()

# 名前付きスペース
let orders = manager.space("orders")
let inventory = manager.space("inventory")
let logs = manager.space("logs")

# 各スペースは完全に独立
await orders.writeAsync(toTuple(strVal("order"), intVal(1001)))
await logs.writeAsync(toTuple(strVal("log"), strVal("info"), strVal("Started")))

データの分離

異なるスペースのデータは完全に分離されています。

let spaceA = manager.space("A")
let spaceB = manager.space("B")

# 同じ構造のタプルを両方に書き込み
await spaceA.writeAsync(toTuple(strVal("data"), intVal(100)))
await spaceB.writeAsync(toTuple(strVal("data"), intVal(200)))

# それぞれ独立して読み取り
let fromA = await spaceA.readAsync(pattern)  # 100
let fromB = await spaceB.readAsync(pattern)  # 200

# Aからtakeしても、Bには影響なし
discard await spaceA.takeAsync(pattern)
let stillInB = await spaceB.tryReadAsync(pattern)  # Some(200)

設計パターン

パターン1: 機能別分離

let jobs = manager.space("jobs")        # ジョブのみ
let results = manager.space("results")  # 結果のみ
let config = manager.space("config")    # 設定のみ

パターン2: テナント別分離(マルチテナント)

proc getSpaceForTenant(tenantId: string): TupleSpace =
  manager.space("tenant_" & tenantId)

let tenantA = getSpaceForTenant("A")
let tenantB = getSpaceForTenant("B")
# 完全にデータが分離される

パターン3: パイプライン(ステージ別)

let input = manager.space("input")
let processing = manager.space("processing")
let output = manager.space("output")

# 各ステージが独立したプロセスで動作

ベストプラクティス

1. 命名規則を決める

# スネークケース + プレフィックス
"job_queue"
"job_results"
"user_sessions"

# または階層的
"app/jobs"
"app/results"
"admin/config"

2. スペースの責務を明確に

# ✅ 単一責務
let jobQueue = manager.space("jobs")      # ジョブのみ
let jobResults = manager.space("results") # 結果のみ

# ❌ 複数責務
let everything = manager.space("all")  # 何でも入る

3. 定数で管理

const
  SPACE_JOBS = "jobs"
  SPACE_RESULTS = "results"
  SPACE_CONFIG = "config"

proc getJobSpace(manager: SpaceManager): TupleSpace =
  manager.space(SPACE_JOBS)

まとめ

学んだこと

トピック ポイント
作成と取得 manager.space("name")
データ分離 スペース間は完全に独立
設計パターン 機能別、テナント別、ステージ別
ベストプラクティス 命名規則、単一責務、定数管理

選び方の指針

状況 推奨
小規模アプリ 単一スペース + タイプタグ
機能が明確に分かれる 機能別スペース
マルチテナント テナント別スペース
パイプライン処理 ステージ別スペース

演習問題

問題7-1: チャットルーム

複数のチャットルームを名前付きスペースで実装してください。

ヒント
  • 各ルームは manager.space("room_" & roomName) で作成
  • メッセージは ("message", userId, text, timestamp) という形式
  • ルーム一覧は manager.spaceNames() で取得可能

問題7-2: キャッシュ層

"primary"と"cache"の2つのスペースを使って、簡単なキャッシュ機構を実装してください。

ヒント
  • まずcacheスペースから検索
  • なければprimaryスペースから取得してcacheに書き込み
  • TTL(Day 10で学ぶ)を使うとさらに本格的に

問題7-3: ジョブ状態管理

jobs, running, completed の3つのスペースを使って、ジョブの状態管理システムを実装してください。

ヒント
  • ジョブ投入: jobsに書き込み
  • ワーカー開始: jobsからtake → runningに書き込み
  • ワーカー完了: runningからtake → completedに書き込み
  • 各スペースの件数で状態を把握

前回: 非同期プログラミング | 目次 | 次回: タイムアウト処理

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?