diff --git a/.github/settings.yml b/.github/settings.yml index c4ad53157683..af989454a6ff 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -21,6 +21,9 @@ labels: - name: area/cursors color: "#D93F0B" description: Issues about cursors + - name: area/diag + color: "#909BA6" + description: Issues about diagnostic commands - name: area/fuzz color: "#D4C5F9" description: Issues about fuzzing and smithing diff --git a/go.mod b/go.mod index 81add749d84c..3be24ed9bb7e 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/FerretDB/FerretDB go 1.21 -toolchain go1.21.1 - require ( github.com/AlekSi/pointer v1.2.0 github.com/SAP/go-hdb v1.5.5 diff --git a/integration/go.mod b/integration/go.mod index 24df7b5c34aa..dc1dbcb4601e 100644 --- a/integration/go.mod +++ b/integration/go.mod @@ -1,6 +1,6 @@ module github.com/FerretDB/FerretDB/integration -go 1.21.1 +go 1.21 replace github.com/FerretDB/FerretDB => ../ diff --git a/internal/backends/collection.go b/internal/backends/collection.go index 081a2492df0a..e927b46253e7 100644 --- a/internal/backends/collection.go +++ b/internal/backends/collection.go @@ -43,6 +43,7 @@ type Collection interface { Explain(context.Context, *ExplainParams) (*ExplainResult, error) Stats(context.Context, *CollectionStatsParams) (*CollectionStatsResult, error) + Compact(context.Context, *CompactParams) (*CompactResult, error) ListIndexes(context.Context, *ListIndexesParams) (*ListIndexesResult, error) CreateIndexes(context.Context, *CreateIndexesParams) (*CreateIndexesResult, error) @@ -214,6 +215,8 @@ func (cc *collectionContract) Explain(ctx context.Context, params *ExplainParams type CollectionStatsParams struct{} // CollectionStatsResult represents the results of Collection.Stats method. +// +// TODO https://github.com/FerretDB/FerretDB/issues/2447 type CollectionStatsResult struct { CountObjects int64 CountIndexes int64 @@ -232,6 +235,28 @@ func (cc *collectionContract) Stats(ctx context.Context, params *CollectionStats return res, err } +// CompactParams represents the parameters of Collection.Compact method. +type CompactParams struct { + Full bool +} + +// CompactResult represents the results of Collection.Compact method. +type CompactResult struct{} + +// Compact reduces the disk space collection takes (by defragmenting, removing dead rows, etc) +// and refreshes its statistics. +// +// If full is true, the operation should try to reduce the disk space as much as possible, +// even if collection or the whole database will be locked for some time. +func (cc *collectionContract) Compact(ctx context.Context, params *CompactParams) (*CompactResult, error) { + defer observability.FuncCall(ctx)() + + res, err := cc.c.Compact(ctx, params) + checkError(err, ErrorCodeDatabaseDoesNotExist, ErrorCodeCollectionDoesNotExist) + + return res, err +} + // ListIndexesParams represents the parameters of Collection.ListIndexes method. type ListIndexesParams struct{} diff --git a/internal/backends/collection_test.go b/internal/backends/collection_test.go index a666f6d4a506..4c1d59046cc5 100644 --- a/internal/backends/collection_test.go +++ b/internal/backends/collection_test.go @@ -132,3 +132,58 @@ func TestCollectionUpdateAll(t *testing.T) { }) } } + +func TestCollectionCompact(t *testing.T) { + t.Skip("https://github.com/FerretDB/FerretDB/issues/3484") + t.Skip("https://github.com/FerretDB/FerretDB/issues/3469") + + t.Parallel() + + ctx := conninfo.Ctx(testutil.Ctx(t), conninfo.New()) + + for _, b := range testBackends(t) { + b := b + t.Run(b.Name(), func(t *testing.T) { + t.Parallel() + + t.Run("DatabaseDoesNotExist", func(t *testing.T) { + t.Parallel() + + dbName, collName := testutil.DatabaseName(t), testutil.CollectionName(t) + cleanupDatabase(t, ctx, b, dbName) + + db, err := b.Database(dbName) + require.NoError(t, err) + + coll, err := db.Collection(collName) + require.NoError(t, err) + + _, err = coll.Compact(ctx, nil) + assertErrorCode(t, err, backends.ErrorCodeDatabaseDoesNotExist) + }) + + t.Run("CollectionDoesNotExist", func(t *testing.T) { + t.Parallel() + + dbName, collName := testutil.DatabaseName(t), testutil.CollectionName(t) + otherCollName := collName + "_other" + cleanupDatabase(t, ctx, b, dbName) + + db, err := b.Database(dbName) + require.NoError(t, err) + + // to create database + err = db.CreateCollection(ctx, &backends.CreateCollectionParams{ + Name: otherCollName, + }) + require.NoError(t, err) + + coll, err := db.Collection(collName) + require.NoError(t, err) + + _, err = coll.Compact(ctx, nil) + assertErrorCode(t, err, backends.ErrorCodeCollectionDoesNotExist) + }) + }) + } +} diff --git a/internal/backends/decorators/dummy/collection.go b/internal/backends/decorators/dummy/collection.go index 7f8568c5d0d6..a0e656f76638 100644 --- a/internal/backends/decorators/dummy/collection.go +++ b/internal/backends/decorators/dummy/collection.go @@ -60,6 +60,11 @@ func (c *collection) Stats(ctx context.Context, params *backends.CollectionStats return c.c.Stats(ctx, params) } +// Compact implements backends.Collection interface. +func (c *collection) Compact(ctx context.Context, params *backends.CompactParams) (*backends.CompactResult, error) { + return c.c.Compact(ctx, params) +} + // ListIndexes implements backends.Collection interface. func (c *collection) ListIndexes(ctx context.Context, params *backends.ListIndexesParams) (*backends.ListIndexesResult, error) { return c.c.ListIndexes(ctx, params) diff --git a/internal/backends/decorators/oplog/collection.go b/internal/backends/decorators/oplog/collection.go index 2c9cd29561b4..86cb83664344 100644 --- a/internal/backends/decorators/oplog/collection.go +++ b/internal/backends/decorators/oplog/collection.go @@ -175,6 +175,11 @@ func (c *collection) Stats(ctx context.Context, params *backends.CollectionStats return c.c.Stats(ctx, params) } +// Compact implements backends.Collection interface. +func (c *collection) Compact(ctx context.Context, params *backends.CompactParams) (*backends.CompactResult, error) { + return c.c.Compact(ctx, params) +} + // ListIndexes implements backends.Collection interface. func (c *collection) ListIndexes(ctx context.Context, params *backends.ListIndexesParams) (*backends.ListIndexesResult, error) { return c.c.ListIndexes(ctx, params) diff --git a/internal/backends/hana/collection.go b/internal/backends/hana/collection.go index 53fa7afb0727..609032f1e0ba 100644 --- a/internal/backends/hana/collection.go +++ b/internal/backends/hana/collection.go @@ -54,6 +54,11 @@ func (c *collection) Stats(ctx context.Context, params *backends.CollectionStats return nil, lazyerrors.New("not implemented yet") } +// Compact implements backends.Collection interface. +func (c *collection) Compact(ctx context.Context, params *backends.CompactParams) (*backends.CompactResult, error) { + return nil, lazyerrors.New("not implemented yet") +} + // ListIndexes implements backends.Collection interface. func (c *collection) ListIndexes(ctx context.Context, params *backends.ListIndexesParams) (*backends.ListIndexesResult, error) { return nil, lazyerrors.New("not implemented yet") diff --git a/internal/backends/helpers_test.go b/internal/backends/helpers_test.go index 5a2c43701c18..ef0cf354e95a 100644 --- a/internal/backends/helpers_test.go +++ b/internal/backends/helpers_test.go @@ -18,6 +18,7 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/FerretDB/FerretDB/internal/backends" @@ -83,3 +84,8 @@ func cleanupDatabase(t *testing.T, ctx context.Context, b backends.Backend, dbNa _ = b.DropDatabase(ctx, p) }) } + +// assertErrorCode asserts that err is *Error with one of the given error codes. +func assertErrorCode(t *testing.T, err error, code backends.ErrorCode, codes ...backends.ErrorCode) { + assert.True(t, backends.ErrorCodeIs(err, code, codes...), "err = %v", err) +} diff --git a/internal/backends/postgresql/collection.go b/internal/backends/postgresql/collection.go index 45acad58ed2f..fc71362e557d 100644 --- a/internal/backends/postgresql/collection.go +++ b/internal/backends/postgresql/collection.go @@ -255,6 +255,12 @@ func (c *collection) Stats(ctx context.Context, params *backends.CollectionStats return new(backends.CollectionStatsResult), nil } +// Compact implements backends.Collection interface. +func (c *collection) Compact(ctx context.Context, params *backends.CompactParams) (*backends.CompactResult, error) { + // TODO https://github.com/FerretDB/FerretDB/issues/3484 + return new(backends.CompactResult), nil +} + // ListIndexes implements backends.Collection interface. func (c *collection) ListIndexes(ctx context.Context, params *backends.ListIndexesParams) (*backends.ListIndexesResult, error) { // TODO https://github.com/FerretDB/FerretDB/issues/3394 diff --git a/internal/backends/sqlite/collection.go b/internal/backends/sqlite/collection.go index b8f808443ef5..7e93bca6ea62 100644 --- a/internal/backends/sqlite/collection.go +++ b/internal/backends/sqlite/collection.go @@ -320,6 +320,12 @@ func (c *collection) Stats(ctx context.Context, params *backends.CollectionStats }, nil } +// Compact implements backends.Collection interface. +func (c *collection) Compact(ctx context.Context, params *backends.CompactParams) (*backends.CompactResult, error) { + // TODO https://github.com/FerretDB/FerretDB/issues/3469 + return new(backends.CompactResult), nil +} + // ListIndexes implements backends.Collection interface. func (c *collection) ListIndexes(ctx context.Context, params *backends.ListIndexesParams) (*backends.ListIndexesResult, error) { db := c.r.DatabaseGetExisting(ctx, c.dbName) diff --git a/tools/go.mod b/tools/go.mod index b978529e807b..9bf69c520e4a 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -1,6 +1,6 @@ module github.com/FerretDB/FerretDB/tools -go 1.21.1 +go 1.21 require ( github.com/BurntSushi/go-sumtype v0.0.0-20221020234012-480526a59796 diff --git a/tools/golangci/go.mod b/tools/golangci/go.mod index b5dd5a51468a..6acc0800ad47 100644 --- a/tools/golangci/go.mod +++ b/tools/golangci/go.mod @@ -2,7 +2,7 @@ module github.com/FerretDB/FerretDB/tools/golangci -go 1.21.1 +go 1.21 require github.com/golangci/golangci-lint v1.54.2