Skip to content

Proposal: Decouple metadata & REST client from Arrow execution dependencies, and add an in-process REST testkit #2044

Description

@slachiewicz

Summary

github.com/apache/iceberg-go is a single Go module, so a consumer that only needs the metadata layer (schema, types, partition specs, table metadata, manifests) or the REST catalog client still links the Arrow execution stack. Measured on main (833e10c): a package main whose only import is _ "github.com/apache/iceberg-go/catalog/rest" builds to a 66 MB unstripped darwin/arm64 binary, against 4.9 MB for the same program importing only net/http, and its go.mod carries 65 indirect requirements.

go list -deps ./catalog/rest shows the chain: catalog/rest → table (plus table/dv, table/internal, table/substrait) → arrow-go/v18/{arrow,compute,parquet,ipc,flight}, substrait-go/v8, geoarrow-go. The root iceberg package now imports Arrow as well (manifest.go, exprs.go, literals.go, transforms.go, types.go, variant_cast.go, variant_extract.go → arrow/decimal128, parquet/variant, geoarrow-go), so the separation described in #399, where all Arrow use was confined to table, no longer holds.

Relationship to earlier issues

Motivation

  1. Metadata-only consumers. Catalog proxies, REST gateways, metadata translation tools (Apache XTable-style bridges), and serverless functions read and write table metadata but never scan data. They pay for Arrow compute, Substrait, and Parquet decoding they cannot use, and inherit arrow-go and aws-sdk-go-v2 version constraints through MVS.
  2. GOOS=js GOARCH=wasm. The root package and io already build for js/wasm. table and catalog/rest do not, and the single failing package is atomicgo.dev/keyboard, reached through pterm, which table/arrow_utils.go imports for progress output. That is a small fix on its own, but it shows how a terminal UI dependency in table reaches a REST client that has no terminal.
  3. Reusable in-process REST catalog for tests. The unit tests in catalog/rest already run without containers against httptest handlers, and the container-backed tests are behind //go:build integration (internal/recipe/docker-compose.yml, apache/iceberg-rest-fixture). What is missing is a stateful, importable in-process REST catalog server that this repo's tests and downstream projects can use to drive a real client end to end (create namespace → create table → commit → load) without Docker, in the way httptest serves net/http.

Precedent in Apache Iceberg (Java)

  • iceberg-api: schemas, types, expressions, partition specs; depends only on bundled Guava.
  • iceberg-core: table metadata JSON, manifests, commit operations, REST client; Jackson, HTTP client, Avro.
  • iceberg-arrow, iceberg-spark, and the other engine modules: vectorized readers and engine adapters.

Proposal

  1. Isolate packages, no new modules yet. Move the Arrow-dependent code in the root package (variant, decimal128 conversions, geoarrow edge-interpolation constants) and the scan and execution code in table into engine-facing sub-packages, so that iceberg, the metadata operations in table, and catalog/rest compile with the standard library plus the pure-Go JSON and Avro path. Whether a separate go.mod follows is a later decision, per Enormous dependency tree — consider "drivers"? #696.
  2. In-process REST catalog testkit. An in-memory implementation of the REST catalog spec (config endpoint, namespaces, tables, commits with requirement validation) exposed as an http.Handler, usable from httptest in this repo's tests and importable by downstream projects.

Next steps

I would like to contribute this incrementally:

  1. The testkit first, since it is additive and unblocks container-less end-to-end client tests.
  2. Then the package isolation, one dependency edge at a time, each PR keeping go build ./... and the existing tests green.

Would the maintainers be open to this direction?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions