actualize items list in db
This commit is contained in:
@ -875,10 +875,17 @@ func parseEwayDumpAction(ctx context.Context, cmd *cli.Command) error {
|
|||||||
var i int
|
var i int
|
||||||
var start int
|
var start int
|
||||||
|
|
||||||
|
seenItems, err := entity.IterIntoMap[string, entity.GoodsItem](repository.GoodsItem().List(ctx)).Map(func(gi entity.GoodsItem) (string, error) {
|
||||||
|
return gi.Articul, nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("making seen items map: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
goodsItems := make([]entity.GoodsItem, 0, batchSize)
|
goodsItems := make([]entity.GoodsItem, 0, batchSize)
|
||||||
productIDs := make([]int, 0, batchSize)
|
productIDs := make([]int, 0, batchSize)
|
||||||
knownCategories := make(map[string]struct{})
|
|
||||||
|
|
||||||
|
knownCategories := make(map[string]struct{})
|
||||||
err = entity.IterWithErr(repository.Category().List(ctx)).Do(func(c entity.Category) error {
|
err = entity.IterWithErr(repository.Category().List(ctx)).Do(func(c entity.Category) error {
|
||||||
knownCategories[c.Name] = struct{}{}
|
knownCategories[c.Name] = struct{}{}
|
||||||
return nil
|
return nil
|
||||||
@ -887,6 +894,8 @@ func parseEwayDumpAction(ctx context.Context, cmd *cli.Command) error {
|
|||||||
return fmt.Errorf("filling known categories: %w", err)
|
return fmt.Errorf("filling known categories: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
itemsUpdated := make(map[string]struct{}, len(seenItems))
|
||||||
|
|
||||||
startFrom := time.Now()
|
startFrom := time.Now()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -918,10 +927,16 @@ func parseEwayDumpAction(ctx context.Context, cmd *cli.Command) error {
|
|||||||
|
|
||||||
goodsItems = goodsItems[:0]
|
goodsItems = goodsItems[:0]
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
pi, err := client.GetProductInfo(ctx, int64(item.Cart))
|
var pi entity.GoodsItemInfo
|
||||||
|
if seenItem, ok := seenItems[item.SKU]; ok {
|
||||||
|
pi.Parameters = seenItem.Parameters
|
||||||
|
pi.PhotoURLs = seenItem.PhotoURLs
|
||||||
|
} else {
|
||||||
|
pi, err = client.GetProductInfo(ctx, int64(item.Cart))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("getting product info: %w", err)
|
return fmt.Errorf("getting product info: %w", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
goodsItem, err := entity.MakeGoodsItem(item, remnants, pi)
|
goodsItem, err := entity.MakeGoodsItem(item, remnants, pi)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -929,8 +944,9 @@ func parseEwayDumpAction(ctx context.Context, cmd *cli.Command) error {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
goodsItems = append(goodsItems, goodsItem)
|
itemsUpdated[goodsItem.Articul] = struct{}{}
|
||||||
|
|
||||||
|
goodsItems = append(goodsItems, goodsItem)
|
||||||
if goodsItem.Type == "" {
|
if goodsItem.Type == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -982,6 +998,13 @@ func parseEwayDumpAction(ctx context.Context, cmd *cli.Command) error {
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for k := range itemsUpdated {
|
||||||
|
delete(seenItems, k)
|
||||||
|
}
|
||||||
|
for k := range seenItems {
|
||||||
|
repository.GoodsItem().Delete(ctx, k)
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,49 @@
|
|||||||
package entity
|
package entity
|
||||||
|
|
||||||
func IterWithErr[T any](t []T, err error) iterWithErr[T] {
|
func IterIntoMap[K comparable, V any](v []V, err error) iterIntoMap[K, V] {
|
||||||
return iterWithErr[T]{
|
bi := IterWithErr(v, err)
|
||||||
|
|
||||||
|
return iterIntoMap[K, V]{
|
||||||
|
baseIter: bi,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type iterIntoMap[K comparable, V any] struct {
|
||||||
|
baseIter[V]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i iterIntoMap[K, V]) Map(f func(V) (K, error)) (map[K]V, error) {
|
||||||
|
if i.err != nil {
|
||||||
|
return nil, i.err
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make(map[K]V, len(i.items))
|
||||||
|
for _, item := range i.items {
|
||||||
|
var key K
|
||||||
|
key, i.err = f(item)
|
||||||
|
if i.err != nil {
|
||||||
|
return nil, i.err
|
||||||
|
}
|
||||||
|
|
||||||
|
out[key] = item
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func IterWithErr[T any](t []T, err error) baseIter[T] {
|
||||||
|
return baseIter[T]{
|
||||||
items: t,
|
items: t,
|
||||||
err: err,
|
err: err,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type iterWithErr[T any] struct {
|
type baseIter[T any] struct {
|
||||||
items []T
|
items []T
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (iter iterWithErr[T]) Do(f func(T) error) error {
|
func (iter baseIter[T]) Do(f func(T) error) error {
|
||||||
if iter.err != nil {
|
if iter.err != nil {
|
||||||
return iter.err
|
return iter.err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ type GoodsItemRepository interface {
|
|||||||
GetByCart(context.Context, int64) (GoodsItem, error)
|
GetByCart(context.Context, int64) (GoodsItem, error)
|
||||||
|
|
||||||
UpsertMany(context.Context, ...GoodsItem) ([]GoodsItem, error)
|
UpsertMany(context.Context, ...GoodsItem) ([]GoodsItem, error)
|
||||||
|
Delete(context.Context, string) (GoodsItem, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type CategoryRepository interface {
|
type CategoryRepository interface {
|
||||||
|
|||||||
@ -21,11 +21,20 @@ const useJSON = false
|
|||||||
|
|
||||||
type goodsItemClient struct {
|
type goodsItemClient struct {
|
||||||
db *badger.DB
|
db *badger.DB
|
||||||
|
|
||||||
|
s itemSerializer[entity.GoodsItem]
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGoodsItemClient(db *badger.DB) *goodsItemClient {
|
func newGoodsItemClient(db *badger.DB, serializeAsJSON bool) *goodsItemClient {
|
||||||
|
var s itemSerializer[entity.GoodsItem]
|
||||||
|
if serializeAsJSON {
|
||||||
|
s = goodsItemJSONSerializer{}
|
||||||
|
} else {
|
||||||
|
s = goodsItemFlatbufSerializer{}
|
||||||
|
}
|
||||||
return &goodsItemClient{
|
return &goodsItemClient{
|
||||||
db: db,
|
db: db,
|
||||||
|
s: s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,17 +77,9 @@ func (c *goodsItemClient) ListIter(
|
|||||||
|
|
||||||
for _, kv := range list.GetKv() {
|
for _, kv := range list.GetKv() {
|
||||||
var gooditem entity.GoodsItem
|
var gooditem entity.GoodsItem
|
||||||
|
gooditem, err = c.s.Deserialize(kv.GetValue())
|
||||||
if useJSON {
|
|
||||||
err = json.Unmarshal(kv.GetValue(), &gooditem)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("deserializing item: %w", err)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gooditem, err = fbs.ParseGoodsItem(kv.GetValue())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bus <- gooditem
|
bus <- gooditem
|
||||||
@ -94,7 +95,6 @@ func (c *goodsItemClient) ListIter(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
zerolog.Ctx(ctx).Warn().Err(err).Msg("unable to orchestrate")
|
zerolog.Ctx(ctx).Warn().Err(err).Msg("unable to orchestrate")
|
||||||
}
|
}
|
||||||
println("finished")
|
|
||||||
}(ctx)
|
}(ctx)
|
||||||
|
|
||||||
return bus, nil
|
return bus, nil
|
||||||
@ -117,17 +117,11 @@ func (c *goodsItemClient) List(
|
|||||||
current := iter.Item()
|
current := iter.Item()
|
||||||
err = current.Value(func(val []byte) error {
|
err = current.Value(func(val []byte) error {
|
||||||
var goodsItem entity.GoodsItem
|
var goodsItem entity.GoodsItem
|
||||||
if useJSON {
|
goodsItem, err = c.s.Deserialize(val)
|
||||||
err := json.Unmarshal(val, &goodsItem)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("deserializing: %w", err)
|
||||||
}
|
|
||||||
} else {
|
|
||||||
goodsItem, err = fbs.ParseGoodsItem(val)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
out = append(out, goodsItem)
|
out = append(out, goodsItem)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -201,6 +195,28 @@ func (c *goodsItemClient) UpsertMany(ctx context.Context, items ...entity.GoodsI
|
|||||||
return items, c.upsertByBatch(ctx, items)
|
return items, c.upsertByBatch(ctx, items)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *goodsItemClient) Delete(ctx context.Context, sku string) (out entity.GoodsItem, err error) {
|
||||||
|
err = c.db.Update(func(txn *badger.Txn) error {
|
||||||
|
skuKey := c.prefixedStr(sku)
|
||||||
|
out, err = c.getBySKU(skuKey, txn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = txn.Delete(skuKey)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("deleting key: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return entity.GoodsItem{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *goodsItemClient) upsertByBatch(ctx context.Context, items []entity.GoodsItem) error {
|
func (c *goodsItemClient) upsertByBatch(ctx context.Context, items []entity.GoodsItem) error {
|
||||||
batch := c.db.NewWriteBatch()
|
batch := c.db.NewWriteBatch()
|
||||||
defer batch.Cancel()
|
defer batch.Cancel()
|
||||||
@ -214,11 +230,9 @@ func (c *goodsItemClient) upsertByBatch(ctx context.Context, items []entity.Good
|
|||||||
}
|
}
|
||||||
|
|
||||||
key := c.prefixedStr(item.Articul)
|
key := c.prefixedStr(item.Articul)
|
||||||
var value []byte
|
value, err := c.s.Serialize(item)
|
||||||
if useJSON {
|
if err != nil {
|
||||||
value, _ = json.Marshal(item)
|
return fmt.Errorf("serializing item: %w", err)
|
||||||
} else {
|
|
||||||
value = fbs.MakeDomainGoodItemFinished(item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
idxValue := make([]byte, len(key))
|
idxValue := make([]byte, len(key))
|
||||||
@ -257,17 +271,43 @@ func (c *goodsItemClient) getBySKU(sku []byte, txn *badger.Txn) (out entity.Good
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = item.Value(func(val []byte) error {
|
err = item.Value(func(val []byte) error {
|
||||||
if useJSON {
|
out, err = c.s.Deserialize(val)
|
||||||
return json.Unmarshal(val, &out)
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err = fbs.ParseGoodsItem(val)
|
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return out, fmt.Errorf("reading value: %w", err)
|
return out, fmt.Errorf("reading value: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type itemSerializer[T any] interface {
|
||||||
|
Serialize(T) ([]byte, error)
|
||||||
|
Deserialize([]byte) (T, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type goodsItemJSONSerializer struct{}
|
||||||
|
|
||||||
|
func (goodsItemJSONSerializer) Serialize(in entity.GoodsItem) ([]byte, error) {
|
||||||
|
return json.Marshal(in)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (goodsItemJSONSerializer) Deserialize(data []byte) (in entity.GoodsItem, err error) {
|
||||||
|
err = json.Unmarshal(data, &in)
|
||||||
|
return in, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type goodsItemFlatbufSerializer struct{}
|
||||||
|
|
||||||
|
func (goodsItemFlatbufSerializer) Serialize(in entity.GoodsItem) ([]byte, error) {
|
||||||
|
out := fbs.MakeDomainGoodItemFinished(in)
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (goodsItemFlatbufSerializer) Deserialize(data []byte) (out entity.GoodsItem, err error) {
|
||||||
|
out, err = fbs.ParseGoodsItem(data)
|
||||||
|
if err != nil {
|
||||||
|
return entity.GoodsItem{}, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user