Documentation
¶
Overview ¶
Package meguri is a distributed web-crawler frontier and rescheduler.
meguri (巡, to make the rounds and revisit on a cycle) is the decision layer of a crawl stack: it turns an endless stream of discovered links into a politely ordered, freshness-aware crawl schedule for a frontier that scales to a hundred billion URLs across a fleet of shared-nothing partitions.
This top-level package holds the data model that every other package shares and that the .meguri file serializes straight: the URLKey and HostKey, the per-URL and per-host durable records, and the discovery and outcome messages. The container itself lives in package format, the in-partition frontier in package frontier, and so on per the package layout in the spec.
The design of record is Spec 2071. The pinned canon: the file extension is .meguri, the magic is MEG1, the URLKey is 128 bits (HostKey high, PathKey low), a partition owns a HostKey range and serializes to one .meguri file, and the build is pure Go with CGO disabled.
Index ¶
Constants ¶
const ( HostFlagTrapSuspect uint16 = 1 << iota HostFlagRobotsMissing HostFlagDeadHost HostFlagGroupingOverride )
Host flag bits, stored in HostRecord.Flags.
Variables ¶
var ( Version = "dev" Commit = "none" Date = "unknown" )
Build stamps, set by the linker at release time (see the Makefile and the GoReleaser config). They default to dev values for a plain `go build`.
Functions ¶
func HostKeyOf ¶
HostKeyOf hashes a host grouping string (a registrable domain or a full host, per the host's HostGrouping) into the 64-bit HostKey. The hash is xxHash64 with seed 0, the fleet convention, so the same grouping always maps to the same partition.
The caller is responsible for producing the canonical grouping string; canonicalization (the CanonPolicy and Public Suffix List rules of doc 03) lands with the seen-set in M2. Until then this is the stable derivation the format and the router agree on.
Types ¶
type AnchorHint ¶
type AnchorHint uint8
AnchorHint is a coarse anchor-text quality bucket carried on a discovery so the prioritizer and the spam guards read it without the full anchor string.
const ( AnchorUnknown AnchorHint = iota // not computed AnchorEmpty // no anchor text AnchorGeneric // "click here", "read more" AnchorDescriptive // real descriptive text AnchorSpammy // matches a spam-anchor pattern )
type Discovery ¶
type Discovery struct {
URLKey URLKey // identity and routing key
CanonicalURL string // the canonical URL text, inline (crosses partitions)
Depth uint16 // source depth + 1, candidate depth
DiscoverySource DiscoverySource // seed | link | sitemap | redirect | manual
SrcHostKey uint64 // HostKey of the page the link was found on
LinkWeight float32 // OPIC cash this link carries from the source
AnchorHint AnchorHint // coarse anchor-text quality bucket
ObservedAt uint32 // epoch-hours, when discovered
}
Discovery is the one-way idempotent message a partition sends when it finds a link for a host it does not own (D16). It is not durable. Idempotency comes from the receiver's seen-set, not from any field here: the same discovery delivered twice deduplicates to one frontier entry, so the transport may be at-least-once.
type DiscoverySource ¶
type DiscoverySource uint8
DiscoverySource records how a URL entered the frontier.
const ( SourceSeed DiscoverySource = iota // from a seed list SourceLink // extracted from a crawled page SourceSitemap // listed in a sitemap SourceRedirect // a redirect target SourceManual // injected by hand )
type HostGrouping ¶
type HostGrouping uint8
HostGrouping is the unit a HostKey groups by: the registrable domain (the default, PSL+1) or the full host.
const ( GroupRegistrableDomain HostGrouping = iota // default: PSL+1 GroupFullHost // each fully-qualified host stands alone )
type HostRecord ¶
type HostRecord struct {
HostKey uint64 // the host group identity
HostRef uint64 // offset into string region, the host group key
Grouping HostGrouping // registrable-domain or full-host
RegistrableRef uint64 // offset into string region, the registrable domain
ResolvedIP [16]byte // cached DNS result, IPv4-mapped into 16 bytes
IPExpiry uint32 // epoch-hours, DNS cache expiry
RobotsFetched uint32 // epoch-hours, robots.txt last fetched
RobotsExpiry uint32 // epoch-hours, robots.txt cache expiry
RobotsRef uint64 // offset into blob region, parsed robots rules
CrawlDelay uint16 // deciseconds, effective crawl delay
HostNextEligible uint32 // epoch-seconds, per-host token bucket
IPNextEligible uint32 // epoch-seconds, per-IP token bucket
URLBudget uint32 // per-host URL cap
URLCount uint32 // current URLs of this host in the frontier
DepthCap uint16 // max crawl depth for this host
HostScore float32 // imported host quality / PageRank, 0 if none
CrawlTotal uint32 // lifetime successful fetches
ErrorTotal uint32 // lifetime failed fetches
AvgLatency uint16 // milliseconds, smoothed fetch latency
Flags uint16 // trap-suspect | robots-missing | dead-host | grouping-override
}
HostRecord is the durable per-host state, one row per host group, keyed and sorted by HostKey. It is the politeness, DNS, and robots state a URL's dispatch reads, plus the per-host budgets and imported quality signal. There are far fewer hosts than URLs, so the host table stays resident while the URL table stays mostly on disk (doc 03).
type HostSignal ¶
HostSignal is one host's imported reputation: the dense per-HostKey host_score tsumugi computes over a prior crawl (doc 09). The blend reads it as the host quality term; a host with no signal falls back to its locally accumulated score.
type Outcome ¶
type Outcome struct {
URLKey URLKey // which URL this outcome is for
HTTPStatus uint16 // the status returned
FetchedAt uint32 // epoch-hours, fetch completion
LatencyMS uint16 // round-trip latency, milliseconds
NotModified bool // 304 from the conditional GET
ContentFP uint64 // fingerprint of the body, 0 if none
Simhash uint64 // near-dup signature, 0 if none
ContentLen uint32 // body length in bytes
ETag string // ETag header, empty if none
LastModified uint32 // epoch-hours, 0 if none
RedirectTarget string // resolved redirect URL, empty if none
Retryable bool // transient failure, retry warranted
RetryAfter uint16 // deciseconds from a Retry-After header, 0 if none
RobotsCrawlDelay uint16 // deciseconds, fresh Crawl-delay if robots re-read
// RobotsBody is the raw robots.txt bytes, populated only for a robots fetch
// (fetch.Request.Robots). Parsing is policy and stays in meguri (doc 07): the
// fetcher hands back the bytes, the frontier turns them into rules.
RobotsBody []byte
Links []Discovery // extracted out-links, canonicalized and ready to route
}
Outcome is the typed result of one fetch, the first-class value that closes the loop (D18). It is not durable: the fetcher returns it through the SPI and the engine consumes it to update the URL's state, its change-rate estimate, its next-due time, its host's adaptive rate, and the importance signals.
A fetch is a request-outcome pair: the engine dispatches a URL and the fetcher returns exactly one Outcome. Freshness reads NotModified, ContentFP, Simhash, and FetchedAt; politeness reads LatencyMS, HTTPStatus, and RobotsCrawlDelay; prioritization reads Links and their per-link cash.
type Signal ¶
type Signal struct {
Epoch uint64 // the import's version, higher supersedes lower
Hosts []HostSignal // dense host reputation
URLs []URLSignal // sparse per-page rank
}
Signal is one tsumugi import bundle (doc 12, D16): a monotonically rising epoch, the dense host scores, and the sparse per-page ranks. It is never depended on: a partition that has not yet imported a bundle still crawls correctly, and a newer epoch overwrites an older one rather than summing, so a dropped or duplicated bundle costs only freshness of the signal, never correctness. The bundle a producer emits spans every partition's hosts; the router splits it so each partition imports only the entries for hosts it owns.
type URLKey ¶
URLKey is the 128-bit identity of a URL in the frontier (D3). The HostKey is the high 64 bits and the PathKey is the low 64 bits. The HostKey is at once the partition key, the politeness key, and the colocation key, so a host's URLs always live together: same partition, same politeness bucket, contiguous in the file.
func MakeURLKey ¶
MakeURLKey builds a URLKey from a host grouping string and the path-and-query remainder. It is the convenience the discovery path uses once a URL is canonicalized.
func URLKeyFromBytes ¶
URLKeyFromBytes decodes the 16-byte form Bytes produces.
func (URLKey) Bytes ¶
Bytes returns the 16-byte on-the-wire form: HostKey then PathKey, each little-endian, matching the file's URLKey field layout (doc 10). The two halves read back as the two u64s with binary.LittleEndian.
func (URLKey) Compare ¶
Compare returns -1, 0, or 1 as a sorts before, equal to, or after b, in the same big-endian 128-bit order as Less.
func (URLKey) Less ¶
Less reports whether a sorts before b when the 128-bit key is read as a big-endian integer: HostKey first, then PathKey. This is the sort order of the URL table (doc 10), and it is what puts a host's rows in one contiguous range. Note the order is logical, not the little-endian byte image the file stores each half in.
type URLRecord ¶
type URLRecord struct {
URLKey URLKey // 128 bits, HostKey || PathKey
HostKey uint64 // high half of URLKey, kept for host joins
Status URLStatus // state-machine state
Priority float32 // OPIC + optional imported PageRank
Depth uint16 // link distance from nearest seed
DiscoverySource DiscoverySource // seed | link | sitemap | redirect | manual
URLRef uint64 // offset into the string region for the canonical URL
FirstSeen uint32 // epoch-hours, first discovery
LastCrawled uint32 // epoch-hours, last successful fetch
LastChanged uint32 // epoch-hours, last observed content change
NextDue uint32 // epoch-hours, next scheduled crawl
Lambda float32 // Poisson change rate, changes/hour
CrawlCount uint32 // successful fetches
ChangeCount uint32 // fetches that saw a change
NoChangeStreak uint16 // consecutive no-change fetches
ETagRef uint64 // offset into string region, 0 if no ETag
LastModified uint32 // epoch-hours, 0 if no Last-Modified
ContentFP uint64 // content fingerprint of last body
Simhash uint64 // near-dup signature of last body
HTTPStatus uint16 // status of last crawl
RedirectRef uint64 // reference to redirect-target record, 0 if none
RetryCount uint8 // consecutive transient failures
ErrorCount uint16 // lifetime failed fetches
}
URLRecord is the durable per-URL crawl state, one row per frontier entry, keyed by URLKey and sorted by URLKey so a host's rows are contiguous. The field names are stable; the frontier, freshness, dedup, prioritization, format, and store packages all reference them. A checkpoint serializes this straight into the URL table columns with no remapping (D1, D12).
type URLSignal ¶
URLSignal is one page's imported PageRank: the sparse per-URLKey rank tsumugi delivers for the pages a prior crawl covered (doc 09). A URL with no signal scores from its host plus OPIC alone.
type URLStatus ¶
type URLStatus uint8
URLStatus is the state-machine state of a frontier entry. The values are stable and stored in the status column (doc 03, doc 10).
const ( StatusDiscovered URLStatus = iota // seen, not yet scheduled StatusScheduled // queued for a first crawl StatusReady // eligible to dispatch now StatusInFlight // dispatched, awaiting an outcome StatusCrawled // fetched at least once StatusDueRecrawl // crawled, due for a refresh StatusGone // 410/404 stable, tombstoned StatusExcludedRobots // disallowed by robots.txt StatusTrapped // flagged by trap detection )
Directories
¶
| Path | Synopsis |
|---|---|
|
Package bench assembles the deterministic per-partition costs of doc 14 into the hundred-billion projection.
|
Package bench assembles the deterministic per-partition costs of doc 14 into the hundred-billion projection. |
|
cmd
|
|
|
corpusstat
command
Command corpusstat derives the engine-consistent record, URL, host, and host-key-range counts over a url-only JSONL corpus, keyed the way the scale and bench harness key it: full-host grouping via frontier.HostOf and meguri.HostKeyOf.
|
Command corpusstat derives the engine-consistent record, URL, host, and host-key-range counts over a url-only JSONL corpus, keyed the way the scale and bench harness key it: full-host grouping via frontier.HostOf and meguri.HostKeyOf. |
|
meguri
command
Command meguri is the CLI front door to the frontier engine and its .meguri files.
|
Command meguri is the CLI front door to the frontier engine and its .meguri files. |
|
strmeasure
command
Command strmeasure is the Spec 2074 M1 string-blob bake-off.
|
Command strmeasure is the Spec 2074 M1 string-blob bake-off. |
|
Package dataset converts a meguri live store to and from Apache Parquet, so a frontier snapshot can be published as a Hugging Face dataset and read back into a .meguri file.
|
Package dataset converts a meguri live store to and from Apache Parquet, so a frontier snapshot can be published as a Hugging Face dataset and read back into a .meguri file. |
|
Package dedup is the seen-set and the content-dedup machinery: the layer that keeps the same URL discovered a thousand times to one frontier entry, and the same content served under a thousand URLs to one crawl (doc 08, D5, D7, D17).
|
Package dedup is the seen-set and the content-dedup machinery: the layer that keeps the same URL discovered a thousand times to one frontier entry, and the same content served under a thousand URLs to one crawl (doc 08, D5, D7, D17). |
|
Package distribute is the multi-partition layer (doc 12): the partition map that says which partition owns a HostKey, the router that sends a discovery to that owner, the control plane that owns the map and its epoch, and the rebalance that moves a host slice from one partition to another by shipping a .meguri file.
|
Package distribute is the multi-partition layer (doc 12): the partition map that says which partition owns a HostKey, the router that sends a discovery to that owner, the control plane that owns the map and its epoch, and the rebalance that moves a host slice from one partition to another by shipping a .meguri file. |
|
Package dns is the host-resolution cache: it maps a host to its resolved IP, honors TTLs, and feeds the per-IP politeness bucket so two hosts behind one address do not dodge rate limits.
|
Package dns is the host-resolution cache: it maps a host to its resolved IP, honors TTLs, and feeds the per-IP politeness bucket so two hosts behind one address do not dodge rate limits. |
|
Package drum is the on-disk seen-set and URL index of a partition (spec 2072 doc 04, Stage B): a real Disk Repository with Update Management (IRLbot, Lee et al.
|
Package drum is the on-disk seen-set and URL index of a partition (spec 2072 doc 04, Stage B): a real Disk Repository with Update Management (IRLbot, Lee et al. |
|
Package engine composes the resident frontier with a fetcher worker pool and the distribution router into the staged, single-writer partition loop of doc 04.
|
Package engine composes the resident frontier with a fetcher worker pool and the distribution router into the staged, single-writer partition loop of doc 04. |
|
Package fetch defines the boundary between the frontier engine and whatever actually retrieves bytes from the network.
|
Package fetch defines the boundary between the frontier engine and whatever actually retrieves bytes from the network. |
|
Package format is the .meguri single-file container: the 64-byte header, the five regions (URL table, host table, schedule index, seen-set filter, string and blob), and the footer written last, bracketed by the magic MEG1 at both ends.
|
Package format is the .meguri single-file container: the 64-byte header, the five regions (URL table, host table, schedule index, seen-set filter, string and blob), and the footer written last, bracketed by the magic MEG1 at both ends. |
|
Package freshness is the rescheduler, the heart of meguri (doc 06).
|
Package freshness is the rescheduler, the heart of meguri (doc 06). |
|
Package frontier is the in-partition crawl frontier: the bounded-memory Mercator-style queue that turns a partition's URL records into a stream of dispatch decisions in priority-then-politeness order.
|
Package frontier is the in-partition crawl frontier: the bounded-memory Mercator-style queue that turns a partition's URL records into a stream of dispatch decisions in priority-then-politeness order. |
|
Package politeness enforces the rules that keep a crawl from hammering a host: the per-host and per-IP token buckets, the crawl-delay derived from robots.txt and adaptive backoff, and the gate that decides when a host's next fetch is eligible.
|
Package politeness enforces the rules that keep a crawl from hammering a host: the per-host and per-IP token buckets, the crawl-delay derived from robots.txt and adaptive backoff, and the gate that decides when a host's next fetch is eligible. |
|
Package prioritize decides crawl order by importance (doc 09, the M5 milestone).
|
Package prioritize decides crawl order by importance (doc 09, the M5 milestone). |
|
Package robots parses robots.txt per RFC 9309 and answers the one question the frontier asks: may meguri fetch this path?
|
Package robots parses robots.txt per RFC 9309 and answers the one question the frontier asks: may meguri fetch this path? |
|
Package scale is the timed, resource-instrumented sibling of the bench package.
|
Package scale is the timed, resource-instrumented sibling of the bench package. |
|
Package seed is the meguri binary seed format, .seed, the raw block-framed corpus input that replaces gzipped JSONL for the scale passes (Spec 2074 doc 08).
|
Package seed is the meguri binary seed format, .seed, the raw block-framed corpus input that replaces gzipped JSONL for the scale passes (Spec 2074 doc 08). |
|
Package sitemap parses the Sitemaps 0.9 protocol (sitemaps.org) into the discoveries the frontier feeds on.
|
Package sitemap parses the Sitemaps 0.9 protocol (sitemaps.org) into the discoveries the frontier feeds on. |
|
Package store is the durable live state store of a partition (doc 11): the hot mutable form of the frontier, log-structured so a crawl update is an append and the log is its own recovery journal (D11).
|
Package store is the durable live state store of a partition (doc 11): the hot mutable form of the frontier, log-structured so a crawl update is an append and the log is its own recovery journal (D11). |