Compare commits

...

5 Commits

Author SHA1 Message Date
a30da61419 v0.0.158 2023-06-10 16:28:50 +02:00
b613b122e3 v0.0.157 2023-06-10 16:22:14 +02:00
d017530444 v0.0.156 2023-06-10 00:19:17 +02:00
8de83cc290 v0.0.155 2023-06-08 16:26:06 +02:00
603ec82b83 v0.0.154 2023-06-08 16:24:53 +02:00
10 changed files with 138 additions and 53 deletions

View File

@@ -11,6 +11,7 @@ import (
"io" "io"
"os" "os"
"path" "path"
"path/filepath"
"regexp" "regexp"
"strings" "strings"
"time" "time"
@@ -24,6 +25,7 @@ type EnumDefVal struct {
type EnumDef struct { type EnumDef struct {
File string File string
FileRelative string
EnumTypeName string EnumTypeName string
Type string Type string
Values []EnumDefVal Values []EnumDefVal
@@ -83,7 +85,7 @@ func GenerateEnumSpecs(sourceDir string, destFile string) error {
for _, f := range files { for _, f := range files {
fmt.Printf("========= %s =========\n\n", f.Name()) fmt.Printf("========= %s =========\n\n", f.Name())
fileEnums, pn, err := processFile(path.Join(sourceDir, f.Name())) fileEnums, pn, err := processFile(sourceDir, path.Join(sourceDir, f.Name()))
if err != nil { if err != nil {
return err return err
} }
@@ -123,7 +125,7 @@ func GenerateEnumSpecs(sourceDir string, destFile string) error {
return nil return nil
} }
func processFile(fn string) ([]EnumDef, string, error) { func processFile(basedir string, fn string) ([]EnumDef, string, error) {
file, err := os.Open(fn) file, err := os.Open(fn)
if err != nil { if err != nil {
return nil, "", err return nil, "", err
@@ -153,8 +155,15 @@ func processFile(fn string) ([]EnumDef, string, error) {
} }
if match, ok := rexEnumDef.MatchFirst(line); ok { if match, ok := rexEnumDef.MatchFirst(line); ok {
rfp, err := filepath.Rel(basedir, fn)
if err != nil {
return nil, "", err
}
def := EnumDef{ def := EnumDef{
File: fn, File: fn,
FileRelative: rfp,
EnumTypeName: match.GroupByName("name").Value(), EnumTypeName: match.GroupByName("name").Value(),
Type: match.GroupByName("type").Value(), Type: match.GroupByName("type").Value(),
Values: make([]EnumDefVal, 0), Values: make([]EnumDefVal, 0),
@@ -239,7 +248,7 @@ func fmtOutput(cs string, enums []EnumDef, pkgname string) string {
str += "// ================================ " + enumdef.EnumTypeName + " ================================" + "\n" str += "// ================================ " + enumdef.EnumTypeName + " ================================" + "\n"
str += "//" + "\n" str += "//" + "\n"
str += "// File: " + enumdef.File + "\n" str += "// File: " + enumdef.FileRelative + "\n"
str += "// StringEnum: " + langext.Conditional(hasStr, "true", "false") + "\n" str += "// StringEnum: " + langext.Conditional(hasStr, "true", "false") + "\n"
str += "// DescrEnum: " + langext.Conditional(hasDescr, "true", "false") + "\n" str += "// DescrEnum: " + langext.Conditional(hasDescr, "true", "false") + "\n"
str += "//" + "\n" str += "//" + "\n"

View File

@@ -1,5 +1,5 @@
package goext package goext
const GoextVersion = "0.0.153" const GoextVersion = "0.0.158"
const GoextVersionTimestamp = "2023-06-08T16:24:15+0200" const GoextVersionTimestamp = "2023-06-10T16:28:50+0200"

View File

@@ -2,13 +2,30 @@ package wmo
import ( import (
"context" "context"
"go.mongodb.org/mongo-driver/bson/bsontype"
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
ct "gogs.mikescher.com/BlackForestBytes/goext/cursortoken" ct "gogs.mikescher.com/BlackForestBytes/goext/cursortoken"
"gogs.mikescher.com/BlackForestBytes/goext/langext" "gogs.mikescher.com/BlackForestBytes/goext/langext"
"reflect" "reflect"
) )
type EntityID = any type EntityID interface {
MarshalBSONValue() (bsontype.Type, []byte, error)
String() string
}
type Decodable interface {
Decode(v any) error
}
type Cursorable interface {
Decode(v any) error
Err() error
Close(ctx context.Context) error
All(ctx context.Context, results any) error
RemainingBatchLength() int
Next(ctx context.Context) bool
}
type fullTypeRef[TData any] struct { type fullTypeRef[TData any] struct {
IsPointer bool IsPointer bool
@@ -21,8 +38,9 @@ type fullTypeRef[TData any] struct {
} }
type Coll[TData any] struct { type Coll[TData any] struct {
coll *mongo.Collection coll *mongo.Collection
dataTypeMap map[string]fullTypeRef[TData] dataTypeMap map[string]fullTypeRef[TData]
customDecoder *func(ctx context.Context, dec Decodable) (TData, error)
} }
func (c *Coll[TData]) Collection() *mongo.Collection { func (c *Coll[TData]) Collection() *mongo.Collection {
@@ -33,6 +51,11 @@ func (c *Coll[TData]) Name() string {
return c.coll.Name() return c.coll.Name()
} }
func (c *Coll[TData]) WithDecodeFunc(cdf func(ctx context.Context, dec Decodable) (TData, error)) *Coll[TData] {
c.customDecoder = langext.Ptr(cdf)
return c
}
func (c *Coll[TData]) Indexes() mongo.IndexView { func (c *Coll[TData]) Indexes() mongo.IndexView {
return c.coll.Indexes() return c.coll.Indexes()
} }

54
wmo/decoding.go Normal file
View File

@@ -0,0 +1,54 @@
package wmo
import (
"context"
)
func (c *Coll[TData]) decodeSingle(ctx context.Context, dec Decodable) (TData, error) {
if c.customDecoder != nil {
return (*c.customDecoder)(ctx, dec)
} else {
var res TData
err := dec.Decode(&res)
if err != nil {
return *new(TData), err
}
return res, nil
}
}
func (c *Coll[TData]) decodeAll(ctx context.Context, cursor Cursorable) ([]TData, error) {
if c.customDecoder != nil {
res := make([]TData, 0, cursor.RemainingBatchLength())
for cursor.Next(ctx) {
entry, err := (*c.customDecoder)(ctx, cursor)
if err != nil {
return nil, err
}
res = append(res, entry)
}
return res, nil
} else {
res := make([]TData, 0, cursor.RemainingBatchLength())
err := cursor.All(ctx, &res)
if err != nil {
return nil, err
}
return res, nil
}
}

View File

@@ -12,11 +12,27 @@ func (c *Coll[TData]) Aggregate(ctx context.Context, pipeline mongo.Pipeline, op
return nil, err return nil, err
} }
res := make([]TData, 0, cursor.RemainingBatchLength()) res, err := c.decodeAll(ctx, cursor)
err = cursor.All(ctx, &res)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return res, nil return res, nil
} }
func (c *Coll[TData]) AggregateOneOpt(ctx context.Context, pipeline mongo.Pipeline, opts ...*options.AggregateOptions) (*TData, error) {
cursor, err := c.coll.Aggregate(ctx, pipeline, opts...)
if err != nil {
return nil, err
}
if cursor.Next(ctx) {
v, err := c.decodeSingle(ctx, cursor)
if err != nil {
return nil, err
}
return &v, nil
}
return nil, nil
}

View File

@@ -6,7 +6,7 @@ import (
"go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo"
) )
func (c *Coll[TData]) DeleteOnebyID(ctx context.Context, id EntityID) error { func (c *Coll[TData]) DeleteOneByID(ctx context.Context, id EntityID) error {
_, err := c.coll.DeleteOne(ctx, bson.M{"_id": id}) _, err := c.coll.DeleteOne(ctx, bson.M{"_id": id})
if err != nil { if err != nil {
return err return err

View File

@@ -8,20 +8,15 @@ import (
) )
func (c *Coll[TData]) FindOne(ctx context.Context, filter bson.M) (TData, error) { func (c *Coll[TData]) FindOne(ctx context.Context, filter bson.M) (TData, error) {
var res TData mongoRes := c.coll.FindOne(ctx, filter)
err := c.coll.FindOne(ctx, filter).Decode(&res) return c.decodeSingle(ctx, mongoRes)
if err != nil {
return *new(TData), err
}
return res, nil
} }
func (c *Coll[TData]) FindOneOpt(ctx context.Context, filter bson.M) (*TData, error) { func (c *Coll[TData]) FindOneOpt(ctx context.Context, filter bson.M) (*TData, error) {
var res TData mongoRes := c.coll.FindOne(ctx, filter)
err := c.coll.FindOne(ctx, filter).Decode(&res) res, err := c.decodeSingle(ctx, mongoRes)
if err == mongo.ErrNoDocuments { if err == mongo.ErrNoDocuments {
return nil, nil return nil, nil
} }
@@ -33,20 +28,15 @@ func (c *Coll[TData]) FindOneOpt(ctx context.Context, filter bson.M) (*TData, er
} }
func (c *Coll[TData]) FindOneByID(ctx context.Context, id EntityID) (TData, error) { func (c *Coll[TData]) FindOneByID(ctx context.Context, id EntityID) (TData, error) {
var res TData mongoRes := c.coll.FindOne(ctx, bson.M{"_id": id})
err := c.coll.FindOne(ctx, bson.M{"_id": id}).Decode(&res) return c.decodeSingle(ctx, mongoRes)
if err != nil {
return *new(TData), err
}
return res, nil
} }
func (c *Coll[TData]) FindOneOptByID(ctx context.Context, id EntityID) (*TData, error) { func (c *Coll[TData]) FindOneOptByID(ctx context.Context, id EntityID) (*TData, error) {
var res TData mongoRes := c.coll.FindOne(ctx, bson.M{"_id": id})
err := c.coll.FindOne(ctx, bson.M{"_id": id}).Decode(&res) res, err := c.decodeSingle(ctx, mongoRes)
if err == mongo.ErrNoDocuments { if err == mongo.ErrNoDocuments {
return nil, nil return nil, nil
} }
@@ -63,8 +53,7 @@ func (c *Coll[TData]) Find(ctx context.Context, filter bson.M, opts ...*options.
return nil, err return nil, err
} }
res := make([]TData, 0, cursor.RemainingBatchLength()) res, err := c.decodeAll(ctx, cursor)
err = cursor.All(ctx, &res)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -11,12 +11,7 @@ func (c *Coll[TData]) InsertOne(ctx context.Context, valueIn TData) (TData, erro
return *new(TData), err return *new(TData), err
} }
var res TData mongoRes := c.coll.FindOne(ctx, bson.M{"_id": insRes.InsertedID})
err = c.coll.FindOne(ctx, bson.M{"_id": insRes.InsertedID}).Decode(&res) return c.decodeSingle(ctx, mongoRes)
if err != nil {
return *new(TData), err
}
return res, nil
} }

View File

@@ -37,10 +37,19 @@ func (c *Coll[TData]) List(ctx context.Context, filter ct.Filter, pageSize *int,
return nil, ct.CursorToken{}, err return nil, ct.CursorToken{}, err
} }
// fast branch
if pageSize == nil {
entries, err := c.decodeAll(ctx, cursor)
if err != nil {
return nil, ct.CursorToken{}, err
}
return entries, ct.End(), nil
}
entities := make([]TData, 0, cursor.RemainingBatchLength()) entities := make([]TData, 0, cursor.RemainingBatchLength())
for (pageSize == nil || len(entities) != *pageSize) && cursor.Next(ctx) { for (pageSize == nil || len(entities) != *pageSize) && cursor.Next(ctx) {
var entry TData var entry TData
err = cursor.Decode(&entry) entry, err = c.decodeSingle(ctx, cursor)
if err != nil { if err != nil {
return nil, ct.CursorToken{}, err return nil, ct.CursorToken{}, err
} }

View File

@@ -8,14 +8,9 @@ import (
) )
func (c *Coll[TData]) FindOneAndUpdate(ctx context.Context, filterQuery bson.M, updateQuery bson.M) (TData, error) { func (c *Coll[TData]) FindOneAndUpdate(ctx context.Context, filterQuery bson.M, updateQuery bson.M) (TData, error) {
var res TData mongoRes := c.coll.FindOneAndUpdate(ctx, filterQuery, updateQuery, options.FindOneAndUpdate().SetReturnDocument(options.After))
err := c.coll.FindOneAndUpdate(ctx, filterQuery, updateQuery, options.FindOneAndUpdate().SetReturnDocument(options.After)).Decode(&res) return c.decodeSingle(ctx, mongoRes)
if err != nil {
return *new(TData), err
}
return res, nil
} }
func (c *Coll[TData]) UpdateOne(ctx context.Context, filterQuery bson.M, updateQuery bson.M) error { func (c *Coll[TData]) UpdateOne(ctx context.Context, filterQuery bson.M, updateQuery bson.M) error {
@@ -55,12 +50,7 @@ func (c *Coll[TData]) ReplaceOne(ctx context.Context, filterQuery bson.M, value
} }
func (c *Coll[TData]) FindOneAndReplace(ctx context.Context, filterQuery bson.M, value TData) (TData, error) { func (c *Coll[TData]) FindOneAndReplace(ctx context.Context, filterQuery bson.M, value TData) (TData, error) {
var res TData mongoRes := c.coll.FindOneAndUpdate(ctx, filterQuery, bson.M{"$set": value}, options.FindOneAndUpdate().SetReturnDocument(options.After))
err := c.coll.FindOneAndUpdate(ctx, filterQuery, bson.M{"$set": value}, options.FindOneAndUpdate().SetReturnDocument(options.After)).Decode(&res) return c.decodeSingle(ctx, mongoRes)
if err != nil {
return *new(TData), err
}
return res, nil
} }