filter

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 28, 2026 License: BSD-2-Clause Imports: 2 Imported by: 0

Documentation

Overview

Package filter provides row-level predicates over format.XRow used by pipe.Copy to select which logical transactions to keep when streaming rows from a reader to a writer.

Filters must NOT mutate the row. The row is logically read-only; callers (and pipe.Copy) rely on this when re-emitting the row downstream. Rows are passed by value, so a filter could not mutate the caller's row anyway — but the contract still holds for clarity.

Filters work on header fields only. None of the constructors below touches BodyRaw — keeping the decode-on-demand promise of the format package intact.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Filter

type Filter func(format.XRow) bool

Filter is a row-level predicate. It returns true to keep the row. Implementations MUST treat the row as read-only.

func And

func And(fs ...Filter) Filter

And returns a Filter that matches when every supplied filter matches. Empty argument list is vacuously true (matches every row).

Example

ExampleAnd composes predicates: keep only INSERT/REPLACE rows from replica 1. And matches a row only when every supplied filter matches it.

package main

import (
	"fmt"

	"github.com/tarantool/go-iproto"

	"github.com/tarantool/go-xlog/filter"
	"github.com/tarantool/go-xlog/format"
)

// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
	return []format.XRow{
		{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
		{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
		{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
	}
}

// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
	var lines []string

	for _, r := range sampleRows() {
		if f(r) {
			lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
		}
	}

	return lines
}

func main() {
	for _, s := range kept(filter.And(
		filter.ReplicaIDs(1),
		filter.Types(iproto.IPROTO_INSERT, iproto.IPROTO_REPLACE),
	)) {
		fmt.Println(s)
	}

}
Output:
INSERT  replica=1 lsn=1
REPLACE replica=1 lsn=2
REPLACE replica=1 lsn=3

func FromVClock

func FromVClock(v format.VClock) Filter

FromVClock keeps rows whose LSN is strictly greater than v[r.ReplicaID]. A replica missing from v is treated as LSN 0, so every positive LSN for that replica passes. Useful for "tail from a given vclock onward".

Example

ExampleFromVClock keeps rows strictly after a per-replica position — the "tail from a given vclock onward" selector. Here replica 1 is advanced past LSN 2 (so only its LSN 3 survives) while replica 2 is absent from the vclock and therefore treated as LSN 0 (so all of its positive LSNs pass).

package main

import (
	"fmt"

	"github.com/tarantool/go-iproto"

	"github.com/tarantool/go-xlog/filter"
	"github.com/tarantool/go-xlog/format"
)

// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
	return []format.XRow{
		{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
		{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
		{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
	}
}

// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
	var lines []string

	for _, r := range sampleRows() {
		if f(r) {
			lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
		}
	}

	return lines
}

func main() {
	for _, s := range kept(filter.FromVClock(format.VClock{1: 2})) {
		fmt.Println(s)
	}

}
Output:
DELETE  replica=2 lsn=1
INSERT  replica=2 lsn=2
REPLACE replica=1 lsn=3

func LSNRange

func LSNRange(rep uint32, lo, hi int64) Filter

LSNRange keeps rows whose ReplicaID == rep AND lo <= LSN <= hi (inclusive on both ends).

Example

ExampleLSNRange keeps rows for one replica whose LSN falls in an inclusive [lo, hi] window.

package main

import (
	"fmt"

	"github.com/tarantool/go-iproto"

	"github.com/tarantool/go-xlog/filter"
	"github.com/tarantool/go-xlog/format"
)

// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
	return []format.XRow{
		{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
		{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
		{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
	}
}

// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
	var lines []string

	for _, r := range sampleRows() {
		if f(r) {
			lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
		}
	}

	return lines
}

func main() {
	for _, s := range kept(filter.LSNRange(1, 2, 3)) {
		fmt.Println(s)
	}

}
Output:
REPLACE replica=1 lsn=2
REPLACE replica=1 lsn=3

func Not

func Not(f Filter) Filter

Not returns a Filter that matches when f does not match.

Example

ExampleNot inverts a predicate: keep every row that is NOT a DELETE.

package main

import (
	"fmt"

	"github.com/tarantool/go-iproto"

	"github.com/tarantool/go-xlog/filter"
	"github.com/tarantool/go-xlog/format"
)

// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
	return []format.XRow{
		{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
		{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
		{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
	}
}

// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
	var lines []string

	for _, r := range sampleRows() {
		if f(r) {
			lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
		}
	}

	return lines
}

func main() {
	for _, s := range kept(filter.Not(filter.Types(iproto.IPROTO_DELETE))) {
		fmt.Println(s)
	}

}
Output:
INSERT  replica=1 lsn=1
REPLACE replica=1 lsn=2
INSERT  replica=2 lsn=2
REPLACE replica=1 lsn=3

func Or

func Or(fs ...Filter) Filter

Or returns a Filter that matches when at least one supplied filter matches. Empty argument list is vacuously false (matches nothing).

Example

ExampleOr keeps a row when at least one supplied filter matches it.

package main

import (
	"fmt"

	"github.com/tarantool/go-iproto"

	"github.com/tarantool/go-xlog/filter"
	"github.com/tarantool/go-xlog/format"
)

// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
	return []format.XRow{
		{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
		{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
		{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
	}
}

// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
	var lines []string

	for _, r := range sampleRows() {
		if f(r) {
			lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
		}
	}

	return lines
}

func main() {
	for _, s := range kept(filter.Or(
		filter.Types(iproto.IPROTO_DELETE),
		filter.ReplicaIDs(2),
	)) {
		fmt.Println(s)
	}

}
Output:
DELETE  replica=2 lsn=1
INSERT  replica=2 lsn=2

func ReplicaIDs

func ReplicaIDs(ids ...uint32) Filter

ReplicaIDs keeps rows whose ReplicaID is in the supplied set. An empty argument list keeps nothing — this matches the "filter is a positive selector" intent.

Example

ExampleReplicaIDs keeps only rows originating from the given replica ids.

package main

import (
	"fmt"

	"github.com/tarantool/go-iproto"

	"github.com/tarantool/go-xlog/filter"
	"github.com/tarantool/go-xlog/format"
)

// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
	return []format.XRow{
		{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
		{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
		{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
	}
}

// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
	var lines []string

	for _, r := range sampleRows() {
		if f(r) {
			lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
		}
	}

	return lines
}

func main() {
	for _, s := range kept(filter.ReplicaIDs(2)) {
		fmt.Println(s)
	}

}
Output:
DELETE  replica=2 lsn=1
INSERT  replica=2 lsn=2

func Types

func Types(types ...iproto.Type) Filter

Types keeps rows whose Type is in the supplied set. Empty argument list keeps nothing (same convention as ReplicaIDs).

Example

ExampleTypes keeps only rows whose request type is in the given set.

package main

import (
	"fmt"

	"github.com/tarantool/go-iproto"

	"github.com/tarantool/go-xlog/filter"
	"github.com/tarantool/go-xlog/format"
)

// sampleRows is a small fixed set of header-only rows used by the filter
// examples. Filters look at header fields only, so BodyRaw is left nil.
func sampleRows() []format.XRow {
	return []format.XRow{
		{Type: iproto.IPROTO_INSERT, ReplicaID: 1, LSN: 1},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 2},
		{Type: iproto.IPROTO_DELETE, ReplicaID: 2, LSN: 1},
		{Type: iproto.IPROTO_INSERT, ReplicaID: 2, LSN: 2},
		{Type: iproto.IPROTO_REPLACE, ReplicaID: 1, LSN: 3},
	}
}

// kept applies f to every sample row and returns a formatted line for each row
// it keeps, so each example can print exactly which rows the predicate selects.
func kept(f filter.Filter) []string {
	var lines []string

	for _, r := range sampleRows() {
		if f(r) {
			lines = append(lines, fmt.Sprintf("%-7s replica=%d lsn=%d", format.TypeName(r.Type), r.ReplicaID, r.LSN))
		}
	}

	return lines
}

func main() {
	for _, s := range kept(filter.Types(iproto.IPROTO_INSERT)) {
		fmt.Println(s)
	}

}
Output:
INSERT  replica=1 lsn=1
INSERT  replica=2 lsn=2

func UntilVClock

func UntilVClock(v format.VClock) Filter

UntilVClock keeps rows whose LSN is <= v[r.ReplicaID]. A replica missing from v is treated as LSN 0, so for that replica only LSN==0 passes (effectively nothing in normal logs). Inverse-ish of FromVClock — note the boundary: FromVClock(v) uses strict >, UntilVClock(v) uses <=, so the row at exactly v[id] belongs to UntilVClock.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL