capture_targets
撮る対象の一覧。 capture-ledger が答える唯一の問い「どの URL を撮るか」の答えがここに
あります。
POST /api/crawls に fromTargets を渡すと、この表の有効な行(呼び出し元の組織のぶんだけ)がクロールの起点になります。
.addColumn("url", "text", (col) => col.notNull().check(sql`url <> '' AND url = btrim(url)`)) .addColumn("url_hash", sql`bytea`, (col) => col.generatedAlwaysAs(sql`digest(url, 'sha256')`).stored(), ) .addColumn("labels", sql`text[]`, (col) => col.notNull().defaultTo(sql`'{}'::text[]`)) .addColumn("enabled", "boolean", (col) => col.notNull().defaultTo(true)) .addColumn("created_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`)) .addColumn("updated_at", "timestamptz", (col) => col.notNull().defaultTo(sql`now()`))| 列 | 要点 |
|---|---|
id |
BIGSERIAL。投入順で、ローダの ORDER BY がそれを保つ |
url |
CHECK (url <> '' AND url = btrim(url)) と CHECK (url ~* '^https?://') — 空文字・前後空白・http(s) でない値をデータベースが拒否する |
url_hash |
生成列。digest(url, 'sha256') を stored 保存。ユニーク索引の土台で、直接読むことはない |
labels |
TEXT[]。もう読んでいない —— 起点にするのは url だけなので、BrowserHive にも成果物のファイル名にも届かない |
enabled |
部分索引 capture_targets_enabled_id_idx が覆う。無効行はコストにならない |
org_id |
この URL がどの組織のものか。既定値は無い —— INSERT では必ず書く。fromTargets はこれで絞るので、他テナントの対象は起点にならない |
created_at / updated_at |
now() 既定。自動更新トリガは今のところ無い |
capture_targets_pkey PRIMARY KEY (id)capture_targets_org_url_hash_key UNIQUE (org_id, url_hash) -- 同じ組織に、同じ URL は 2 度入らないcapture_targets_enabled_id_idx (id) WHERE enabled -- 部分索引capture_targets_enabled_id_idx が部分索引なのは、読み取りが必ず WHERE enabled を
伴うためです。無効な行まで索引に入れても場所の無駄になります。
pnpm run targets add https://example.com/ --org acmeこの表に直接書く、開発用の CLI です。
DB の側では、同じ組織に同じ URL の行を 2 本目に入れようとすると、capture_targets_org_url_hash_key で弾かれます。
別の組織なら、同じ URL を入れられます。
CLI のほかの使い方と、手で足す SQL は、URL ソースにあります。