github.com/weaviate/weaviate@v1.24.6/usecases/objects/replication.go (about)

     1  //                           _       _
     2  // __      _____  __ ___   ___  __ _| |_ ___
     3  // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \
     4  //  \ V  V /  __/ (_| |\ V /| | (_| | ||  __/
     5  //   \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___|
     6  //
     7  //  Copyright © 2016 - 2024 Weaviate B.V. All rights reserved.
     8  //
     9  //  CONTACT: hello@weaviate.io
    10  //
    11  
    12  package objects
    13  
    14  import (
    15  	"encoding/json"
    16  	"fmt"
    17  
    18  	"github.com/go-openapi/strfmt"
    19  	"github.com/weaviate/weaviate/entities/models"
    20  	"github.com/weaviate/weaviate/entities/storobj"
    21  )
    22  
    23  // VObject is a versioned object for detecting replication inconsistencies
    24  type VObject struct {
    25  	// LatestObject is to most up-to-date version of an object
    26  	LatestObject *models.Object `json:"object,omitempty"`
    27  
    28  	Vector  []float32      `json:"vector"`
    29  	Vectors models.Vectors `json:"vectors"`
    30  
    31  	// StaleUpdateTime is the LastUpdateTimeUnix of the stale object sent to the coordinator
    32  	StaleUpdateTime int64 `json:"updateTime,omitempty"`
    33  
    34  	// Version is the most recent incremental version number of the object
    35  	Version uint64 `json:"version"`
    36  }
    37  
    38  // vobjectMarshaler is a helper for the methods implementing encoding.BinaryMarshaler
    39  //
    40  // Because models.Object has an optimized custom MarshalBinary method, that is what
    41  // we want to use when serializing, rather than json.Marshal. This is just a thin
    42  // wrapper around the model bytes resulting from the underlying call to MarshalBinary
    43  type vobjectMarshaler struct {
    44  	StaleUpdateTime int64
    45  	Version         uint64
    46  	Vector          []float32
    47  	Vectors         models.Vectors
    48  	LatestObject    []byte
    49  }
    50  
    51  func (vo *VObject) MarshalBinary() ([]byte, error) {
    52  	b := vobjectMarshaler{
    53  		StaleUpdateTime: vo.StaleUpdateTime,
    54  		Vector:          vo.Vector,
    55  		Vectors:         vo.Vectors,
    56  		Version:         vo.Version,
    57  	}
    58  	if vo.LatestObject != nil {
    59  		obj, err := vo.LatestObject.MarshalBinary()
    60  		if err != nil {
    61  			return nil, fmt.Errorf("marshal object: %w", err)
    62  		}
    63  		b.LatestObject = obj
    64  	}
    65  
    66  	return json.Marshal(b)
    67  }
    68  
    69  func (vo *VObject) UnmarshalBinary(data []byte) error {
    70  	var b vobjectMarshaler
    71  
    72  	err := json.Unmarshal(data, &b)
    73  	if err != nil {
    74  		return err
    75  	}
    76  	vo.StaleUpdateTime = b.StaleUpdateTime
    77  	vo.Vector = b.Vector
    78  	vo.Vectors = b.Vectors
    79  	vo.Version = b.Version
    80  
    81  	if b.LatestObject != nil {
    82  		var obj models.Object
    83  		err = obj.UnmarshalBinary(b.LatestObject)
    84  		if err != nil {
    85  			return fmt.Errorf("unmarshal object: %w", err)
    86  		}
    87  		vo.LatestObject = &obj
    88  	}
    89  
    90  	return nil
    91  }
    92  
    93  // Replica represents a replicated data item
    94  type Replica struct {
    95  	ID      strfmt.UUID     `json:"id,omitempty"`
    96  	Deleted bool            `json:"deleted"`
    97  	Object  *storobj.Object `json:"object,omitempty"`
    98  }
    99  
   100  // robjectMarshaler is a helper for the methods implementing encoding.BinaryMarshaler
   101  //
   102  // Because *storobj.Object has an optimized custom MarshalBinary method, that is what
   103  // we want to use when serializing, rather than json.Marshal. This is just a thin
   104  // wrapper around the storobj bytes resulting from the underlying call to MarshalBinary
   105  type robjectMarshaler struct {
   106  	ID      strfmt.UUID
   107  	Deleted bool
   108  	Object  []byte
   109  }
   110  
   111  func (r *Replica) MarshalBinary() ([]byte, error) {
   112  	b := robjectMarshaler{ID: r.ID, Deleted: r.Deleted}
   113  	if r.Object != nil {
   114  		obj, err := r.Object.MarshalBinary()
   115  		if err != nil {
   116  			return nil, fmt.Errorf("marshal object: %w", err)
   117  		}
   118  		b.Object = obj
   119  	}
   120  
   121  	return json.Marshal(b)
   122  }
   123  
   124  func (r *Replica) UnmarshalBinary(data []byte) error {
   125  	var b robjectMarshaler
   126  
   127  	err := json.Unmarshal(data, &b)
   128  	if err != nil {
   129  		return err
   130  	}
   131  	r.ID = b.ID
   132  	r.Deleted = b.Deleted
   133  
   134  	if b.Object != nil {
   135  		var obj storobj.Object
   136  		err = obj.UnmarshalBinary(b.Object)
   137  		if err != nil {
   138  			return fmt.Errorf("unmarshal object: %w", err)
   139  		}
   140  		r.Object = &obj
   141  	}
   142  
   143  	return nil
   144  }
   145  
   146  type Replicas []Replica
   147  
   148  func (ro Replicas) MarshalBinary() ([]byte, error) {
   149  	ms := make([]robjectMarshaler, len(ro))
   150  
   151  	for i, obj := range ro {
   152  		m := robjectMarshaler{ID: obj.ID, Deleted: obj.Deleted}
   153  		if obj.Object != nil {
   154  			b, err := obj.Object.MarshalBinary()
   155  			if err != nil {
   156  				return nil, fmt.Errorf("marshal object %q: %w", obj.ID, err)
   157  			}
   158  			m.Object = b
   159  		}
   160  		ms[i] = m
   161  	}
   162  
   163  	return json.Marshal(ms)
   164  }
   165  
   166  func (ro *Replicas) UnmarshalBinary(data []byte) error {
   167  	var ms []robjectMarshaler
   168  
   169  	err := json.Unmarshal(data, &ms)
   170  	if err != nil {
   171  		return err
   172  	}
   173  
   174  	reps := make(Replicas, len(ms))
   175  	for i, m := range ms {
   176  		rep := Replica{ID: m.ID, Deleted: m.Deleted}
   177  		if m.Object != nil {
   178  			var obj storobj.Object
   179  			err = obj.UnmarshalBinary(m.Object)
   180  			if err != nil {
   181  				return fmt.Errorf("unmarshal object %q: %w", m.ID, err)
   182  			}
   183  			rep.Object = &obj
   184  		}
   185  		reps[i] = rep
   186  	}
   187  
   188  	*ro = reps
   189  	return nil
   190  }
   191  
   192  // UpdateTime return update time if it exists and 0 otherwise
   193  func (r Replica) UpdateTime() int64 {
   194  	if r.Object != nil {
   195  		return r.Object.LastUpdateTimeUnix()
   196  	}
   197  	return 0
   198  }