github.com/mailru/activerecord@v1.12.2/internal/pkg/generator/tmpl/octopus/main.tmpl (about)

     1  package {{ .ARPkg }}
     2  
     3  import (
     4  	"bytes"
     5  	"context"
     6  	"fmt"
     7  	"log"
     8  {{ if eq .Server.Conf "" -}}
     9  	"time"
    10  {{ end }}
    11  	"strings"
    12  
    13  	"github.com/mailru/activerecord/pkg/iproto/iproto"
    14  	"github.com/mailru/activerecord/pkg/activerecord"
    15  	"github.com/mailru/activerecord/pkg/octopus"
    16  {{- range $ind, $imp := .Imports }}
    17  	{{ if ne $imp.ImportName "" }}{{ $imp.ImportName }} {{ end }}"{{ $imp.Path }}"
    18  {{- end }}
    19  {{- range $i, $imp := addImport .FieldList }}
    20  	"{{ $imp }}"
    21  {{- end }}
    22  )
    23  {{ $pkgName := .ARPkg }}
    24  {{ $serializers := .Serializers -}}
    25  {{ $mutators := .Mutators -}}
    26  {{ $PublicStructName := .ARPkgTitle -}}
    27  {{ $LinkedObject := .LinkedObject }}
    28  {{ $flags := .Flags }}
    29  {{ $fields := .FieldList }}
    30  {{ $procfields := .ProcOutFieldList }}
    31  {{ $procInLen := len .ProcInFieldList }}
    32  {{ $mutatorLen := len .Mutators }}
    33  
    34      {{ if ne $mutatorLen 0 -}}
    35      type Mutators struct {
    36      {{- range $i, $mut := $mutators }}
    37          {{$mut.Name}}    octopus.MutatorField
    38  		field{{ $mut.Name }}Original {{$mut.Type}}
    39      {{- end }}
    40      }
    41      {{ end -}}
    42  
    43  {{ if $fields }}
    44      type {{ $PublicStructName }} struct {
    45          octopus.BaseField
    46          {{- if ne $mutatorLen 0 }}
    47          Mutators
    48          {{- end -}}
    49      {{- range $ind, $fstruct := .FieldList -}}
    50          {{ $rtype := $fstruct.Format -}}
    51          {{ $serlen := len $fstruct.Serializer -}}
    52          {{ if ne $serlen 0 -}}
    53              {{ $sname := index $fstruct.Serializer 0 -}}
    54              {{ $serializer := index $serializers $sname -}}
    55              {{ $rtype = $serializer.Type -}}
    56          {{ end }}
    57          field{{ $fstruct.Name }} {{ $rtype -}}
    58      {{ end }}
    59      }
    60  
    61      type {{ $PublicStructName }}List []*{{ $PublicStructName }}
    62  
    63      const (
    64          namespace uint32 = {{ .Container.ObjectName }}
    65          cntFields uint32 = {{ len .FieldList }}
    66      {{- range $fieldname, $flag := .Flags -}}
    67          {{ range $i, $flagname := $flag.Flags }}
    68          {{ $fieldname }}{{ $flagname }}Flag = 1 << {{ $i -}}
    69          {{ end -}}
    70      {{ end }}
    71      )
    72  
    73      {{ if .Triggers.RepairTuple.Params.Defaults -}}
    74      var defaultValue = [][]byte{
    75      {{- $notfirst := false -}}
    76      {{ range $ind, $fstruct := .FieldList -}}
    77          {{ $packerparam := packerParam $fstruct.Format -}}
    78          {{ if $notfirst }},{{ end -}}
    79          {{ $notfirst = true }}
    80          {{ $packerparam.DefaultValue -}}
    81      {{ end -}}
    82      }
    83      {{- end }}
    84  {{end}}
    85  
    86  {{ if $procfields }}
    87  // proc struct
    88  type {{ $PublicStructName }} struct {
    89      params {{ $PublicStructName }}Params
    90  {{- range $ind, $fstruct := .ProcOutFieldList }}
    91      {{ $rtype := $fstruct.Format -}}
    92      {{ $serlen := len $fstruct.Serializer -}}
    93      {{ if ne $serlen 0 -}}
    94          {{ $sname := index $fstruct.Serializer 0 -}}
    95          {{ $serializer := index $serializers $sname -}}
    96          {{ $rtype = $serializer.Type -}}
    97      {{ end -}}
    98      field{{- $fstruct.Name }} {{ $rtype -}}
    99  {{ end }}
   100  }
   101  
   102  type {{ $PublicStructName }}List []*{{ $PublicStructName }}
   103  
   104  const (
   105      procName string = "{{ .Container.ObjectName }}"
   106      cntOutFields uint32 = {{ len .ProcOutFieldList }}
   107      )
   108  
   109  {{- range $ind, $fstruct := .ProcOutFieldList -}}
   110  {{ $rtype := $fstruct.Format -}}
   111  {{ $sname := $fstruct.Serializer.Name -}}
   112  {{ if ne $sname "" -}}
   113      {{ $serializer := index $serializers $sname -}}
   114      {{ $rtype = $serializer.Type -}}
   115  {{ end }}
   116      func (obj *{{ $PublicStructName }}) Get{{ $fstruct.Name }}() {{ $rtype }} {
   117          return obj.field{{ $fstruct.Name }}
   118      }
   119  {{ end }}
   120  
   121  type {{ $PublicStructName }}Params struct {
   122  {{- range $ind, $fstruct := .ProcInFieldList -}}
   123      {{ $rtype := $fstruct.Format -}}
   124      {{ $serlen := len $fstruct.Serializer -}}
   125      {{ if ne $serlen 0 -}}
   126          {{ $sname := index $fstruct.Serializer 0 -}}
   127          {{ $serializer := index $serializers $sname -}}
   128          {{ $rtype = $serializer.Type -}}
   129      {{ end }}
   130      {{ $fstruct.Name }} {{ $rtype -}}
   131  {{ end }}
   132  }
   133  
   134  func (obj *{{ $PublicStructName }}) GetParams() {{ $PublicStructName }}Params {
   135      return obj.params
   136  }
   137  
   138  func  (obj *{{ $PublicStructName }}) setParams(params {{ $PublicStructName }}Params) error {
   139  	obj.params = params
   140  
   141  	return nil
   142  }
   143  
   144  {{ if ne $procInLen 0 }}
   145  func (obj *{{ $PublicStructName }}Params) arrayValues() ([]string, error)  {
   146  ret := []string{}
   147  {{ range $ind, $fstruct := .ProcInFieldList -}}
   148      {{ $sname := $fstruct.Serializer.Name -}}
   149  	{{ $bvar :=  $fstruct.Name -}}
   150  	{{ if ne $sname "" -}}
   151  		{{ $serializer := index $serializers $sname -}}
   152  		{{ $serparams := $fstruct.Serializer.Params -}}
   153  	pvar{{ $fstruct.Name }}, err := {{ $serializer.ImportName }}.{{ $serializer.Marshaler }}({{ $serparams }}obj.{{ $bvar }})
   154  	if err != nil {
   155  		return nil, fmt.Errorf("error marshal param field {{ $fstruct.Name }}: %w", err)
   156  	}
   157  
   158          {{ if eq $fstruct.Format "[]string" }}
   159          ret = append(ret, pvar{{ $fstruct.Name }}...)
   160  	    {{ else }}
   161  	    ret = append(ret, string(pvar{{ $fstruct.Name }}))
   162  	    {{- end }}
   163  	{{- else -}}
   164  	ret = append(ret, string(obj.{{ $fstruct.Name }}))
   165  	{{- end }}
   166  {{ end }}
   167  	return ret, nil
   168  }
   169  {{ end }}
   170  
   171  func (obj {{ $PublicStructName }}Params) PK() string {
   172      return fmt.Sprint({{ if ne $procInLen 0 }}obj.arrayValues(){{ end }})
   173  }
   174  
   175  func Call(ctx context.Context{{ if ne $procInLen 0 }}, params {{ $PublicStructName }}Params{{ end }}) (*{{ $PublicStructName }}, error) {
   176      return call(ctx{{ if ne $procInLen 0 }}, params{{ end }}, activerecord.ReplicaOrMasterInstanceType)
   177  }
   178  
   179  func CallOnMaster(ctx context.Context{{ if ne $procInLen 0 }}, params {{ $PublicStructName }}Params{{ end }}) (*{{ $PublicStructName }}, error) {
   180      return call(ctx{{ if ne $procInLen 0 }}, params{{ end }}, activerecord.MasterInstanceType)
   181  }
   182  
   183  func call(ctx context.Context{{ if ne $procInLen 0 }}, params {{ $PublicStructName }}Params{{ end }}, instanceType activerecord.ShardInstanceType) (*{{ $PublicStructName }}, error) {
   184  	logger := activerecord.Logger()
   185  	ctx = logger.SetLoggerValueToContext(ctx, map[string]interface{}{"LuaProc": procName})
   186  	metricTimer := activerecord.Metric().Timer("octopus", "{{ $PublicStructName }}")
   187  	metricErrCnt := activerecord.Metric().ErrorCount("octopus", "{{ $PublicStructName }}")
   188  
   189      metricTimer.Timing(ctx, "call_proc")
   190  
   191  	connection, err := octopus.Box(ctx, 0, instanceType, "arcfg", nil)
   192  	if err != nil {
   193  		metricErrCnt.Inc(ctx, "call_proc_preparebox", 1)
   194  		logger.Error(ctx, fmt.Sprintf("Error get box '%s'", err))
   195  
   196  		return nil, err
   197  	}
   198  
   199  	var args []string
   200  	{{ if ne $procInLen 0 }}
   201  	args, err = params.arrayValues()
   202  	if err != nil {
   203  		metricErrCnt.Inc(ctx, "call_proc_preparebox", 1)
   204  		return nil, fmt.Errorf("Error parse args of procedure %s: %w", procName, err)
   205  	}
   206  	{{ end }}
   207  
   208  	td, err := octopus.CallLua(ctx, connection, procName, args...)
   209  	if err != nil {
   210  		metricErrCnt.Inc(ctx, "call_proc", 1)
   211  		return nil, fmt.Errorf("call lua procedure %s: %w", procName, err)
   212  	}
   213  
   214      if len(td) != 1 {
   215          return nil, fmt.Errorf("invalid response len from lua call: %d. Only one tuple supported", len(td))
   216      }
   217  
   218  	ret, err := TupleToStruct(ctx, td[0])
   219  	if err != nil {
   220  		metricErrCnt.Inc(ctx, "call_proc_preparebox", 1)
   221  		logger.Error(ctx, "Error in response: ", err)
   222  
   223  		return nil, err
   224  	}
   225  
   226  	metricTimer.Finish(ctx, "call_proc")
   227  
   228  	activerecord.Logger().CollectQueries(ctx, CallMockerLogger({{ if ne $procInLen 0 }}params, {{ end }}{{ $PublicStructName }}List([]*{{ $PublicStructName }}{ret})))
   229  
   230  	return ret, nil
   231  }
   232  
   233  func TupleToStruct(ctx context.Context, tuple octopus.TupleData) (*{{ $PublicStructName }}, error) {
   234      if tuple.Cnt < cntOutFields {
   235          return nil, fmt.Errorf("not enought selected fields %d in response tuple: %d but expected %d fields", tuple.Cnt, tuple.Cnt, cntOutFields)
   236      }
   237  
   238  	np := {{ $PublicStructName }}{}
   239  
   240  	{{ range $ind, $fstruct := .ProcOutFieldList -}}
   241  	val{{ $fstruct.Name }}, err := Unpack{{ $fstruct.Name -}}(bytes.NewReader(tuple.Data[{{$ind}}]))
   242  	if err != nil {
   243  		return nil, err
   244  	}
   245  
   246  	np.field{{ $fstruct.Name }} = val{{ $fstruct.Name }}
   247  	{{ end }}
   248  
   249  	return &np, nil
   250  }
   251  
   252  {{ range $ind, $fstruct := .ProcOutFieldList -}}
   253  	{{ $packerparam := packerParam $fstruct.Format -}}
   254  	{{ $rtype := $fstruct.Format -}}
   255  	{{ $sname := $fstruct.Serializer.Name -}}
   256  	{{ if ne $sname "" -}}
   257  		{{ $serializer := index $serializers $sname -}}
   258  		{{ $rtype = $serializer.Type -}}
   259  	{{ end -}}
   260  func (obj *{{ $PublicStructName }}) Set{{ $fstruct.Name }}({{ $fstruct.Name }} {{ $rtype }}) error {
   261  	obj.field{{ $fstruct.Name }} = {{ $fstruct.Name}}
   262  
   263  	return nil
   264  }
   265  
   266  func Unpack{{ $fstruct.Name }}(r *bytes.Reader) (ret {{ $rtype }}, errRet error) {
   267  	var {{ $fstruct.Name }} {{ if ne $packerparam.UnpackType "" }}{{ $packerparam.UnpackType }}{{ else }}{{ $fstruct.Format }}{{ end }}
   268  	{{ $isPointer := hasPrefix (printf "%s" $rtype) "*" }}
   269  
   270  	err := {{ $packerparam.UnpackFunc }}(r, &{{ $fstruct.Name }}, iproto.ModeDefault)
   271  	if err != nil {
   272  		errRet = fmt.Errorf("error unpack field {{ $fstruct.Name }} in tuple: '%w'", err)
   273  		return
   274  	}
   275  
   276  	bvar := {{ if ne $packerparam.UnpackConvFunc "" -}}
   277  		{{ $packerparam.UnpackConvFunc }}({{ $fstruct.Name }})
   278  	{{ else -}}
   279  		{{ $fstruct.Name }}
   280  	{{ end -}}
   281  
   282  	{{ $underlyingType := trimPrefix (printf "%s" $rtype) "*"}}
   283  	{{ if ne $sname "" -}}
   284  		{{ $serializer := index $serializers $sname -}}
   285  		{{ $serparams := $fstruct.Serializer.Params }}
   286  
   287  	var svar {{$rtype}}
   288  
   289  	err = {{ $serializer.ImportName }}.{{ $serializer.Unmarshaler }}({{ $serparams }}bvar, &svar)
   290  	if err != nil {
   291  		errRet = fmt.Errorf("error unmarshal field {{ $fstruct.Name }}: %w", err)
   292  		return
   293  	}
   294  
   295  	{{ else -}}
   296  	svar := bvar
   297  
   298  	{{ end -}}
   299  
   300  	return svar, nil
   301  }
   302  
   303  func pack{{ $fstruct.Name }}(w []byte, {{ $fstruct.Name }} {{ $rtype }}) ([]byte, error) {
   304  	{{ $bvar :=  $packerparam.PackConvFunc $fstruct.Name -}}
   305  	{{ if ne $sname "" -}}
   306  		{{ $serializer := index $serializers $sname -}}
   307  		{{ $serparams := $fstruct.Serializer.Params -}}
   308  	pvar, err := {{ $serializer.ImportName }}.{{ $serializer.Marshaler }}({{ $serparams }}{{ $bvar }})
   309  	if err != nil {
   310  		return nil, fmt.Errorf("error marshal field {{ $fstruct.Name }}: %w", err)
   311  	}
   312  	{{- else -}}
   313  	pvar := {{ $bvar }}
   314  	{{- end }}
   315  
   316  	return {{ $packerparam.PackFunc }}(w, pvar, iproto.ModeDefault), nil
   317  }
   318  {{ end }}
   319  // end proc struct
   320  
   321  {{end}}
   322  
   323  {{ if eq .Server.Conf "" -}}
   324  var boxOption, _ = octopus.NewOptions(
   325  	"{{ .Server.Host }}:{{ .Server.Port }}",
   326  	octopus.ModeMaster,
   327  	octopus.WithTimeout(time.Millisecond * {{ .Server.Timeout }}, time.Millisecond * {{ .Server.Timeout }}),
   328  )
   329  
   330  var clusterInfo = activerecord.NewClusterInfo(
   331  	activerecord.WithShard([]activerecord.OptionInterface{boxOption}, []activerecord.OptionInterface{}),
   332  ){{ end }}
   333  
   334  func New(ctx context.Context) *{{ $PublicStructName }} {
   335  	newObj := {{ $PublicStructName }}{}
   336  	{{- if $fields }}
   337  	newObj.BaseField.UpdateOps = []octopus.Ops{}
   338  	newObj.BaseField.ExtraFields = [][]byte{}
   339  	newObj.BaseField.Objects = map[string][]octopus.ModelStruct{}
   340      {{ end }}
   341      {{- if ne $mutatorLen 0 -}}
   342      {{- range $i, $mut := $mutators }}
   343      newObj.{{$mut.Name}}.PartialFields = map[string]any{}
   344      {{ if ne $mut.Update "" -}}
   345      newObj.{{$mut.Name}}.OpFunc = map[octopus.OpCode]string{octopus.OpUpdate: "{{$mut.Update}}"}
   346      {{ end }}
   347      {{ if ne $mut.Replace "" -}}
   348      newObj.{{$mut.Name}}.OpFunc = map[octopus.OpCode]string{octopus.OpInsert: "{{$mut.Replace}}"}
   349      {{ end }}
   350      {{- end }}
   351      {{ end }}
   352  	return &newObj
   353  }
   354  
   355  {{- if .Triggers.RepairTuple }}
   356  func repairTuple(ctx context.Context, tuple *octopus.TupleData) error {
   357  	{{- if .Triggers.RepairTuple.ImportName }}
   358  	logger := activerecord.Logger()
   359  
   360  	logger.Debug(ctx, "{{ $PublicStructName }}", "Repair trigger called")
   361  
   362  	err := {{ .Triggers.RepairTuple.ImportName }}.{{ .Triggers.RepairTuple.Func }}(tuple, cntFields)
   363  	if err != nil {
   364  		return fmt.Errorf("trigger can't repair tuple %w", err)
   365  	}
   366  	{{- else if .Triggers.RepairTuple.Params.Defaults }}
   367  	logger := activerecord.Logger()
   368  
   369  	logger.Warn(ctx, "{{ $PublicStructName }}", "Repair trigger set defaults")
   370  	for f := tuple.Cnt; f < cntFields; f++ {
   371  		tuple.Data = append(tuple.Data, defaultValue[f])
   372  	}
   373  	tuple.Cnt = cntFields
   374  	{{- end }}
   375  
   376  	return nil
   377  }
   378  {{- end }}
   379  
   380  {{ if $fields }}
   381  func TupleToStruct(ctx context.Context, tuple octopus.TupleData) (*{{ $PublicStructName }}, error) {
   382  	np := New(ctx)
   383  
   384  	{{ range $ind, $fstruct := .FieldList -}}
   385  	val{{ $fstruct.Name }}, err := Unpack{{ $fstruct.Name -}}(bytes.NewReader(tuple.Data[{{$ind}}]))
   386  	if err != nil {
   387  		return nil, err
   388  	}
   389  
   390  	np.Set{{ $fstruct.Name }}(val{{ $fstruct.Name }})
   391  	{{ end }}
   392  
   393  	np.BaseField.Exists = true
   394  	np.BaseField.UpdateOps = []octopus.Ops{}
   395  	{{if gt $mutatorLen 0}}
   396  	np.ClearMutatorUpdateOpts()
   397  	{{end}}
   398  
   399  	if tuple.Cnt > cntFields {
   400  		logger := activerecord.Logger()
   401  
   402  		logger.Warn(ctx, "{{ $PublicStructName }}", np.PrimaryString(), "Extra fields")
   403  
   404  		np.BaseField.ExtraFields = tuple.Data[cntFields:]
   405  	}
   406  
   407  	return np, nil
   408  }
   409  
   410  func NewFromBox(ctx context.Context, tuples []octopus.TupleData) ([]*{{ $PublicStructName }}, error) {
   411  	logger := activerecord.Logger()
   412  
   413  	logger.Debug(ctx, "{{ $PublicStructName }}", fmt.Sprintf("Cnt tuples %d", len(tuples)))
   414  
   415  	ret := make([]*{{ $PublicStructName }}, 0, len(tuples))
   416  
   417  	for num, tuple := range tuples {
   418  		var repaired bool
   419  		{{- if .Triggers.RepairTuple }}
   420  
   421  		if tuple.Cnt != cntFields {
   422  			err := repairTuple(ctx, &tuple)
   423  			if err != nil {
   424  				logger.Error(ctx, "{{ $PublicStructName }}", fmt.Errorf("%d tuple in response has %d fields but expected: %d. Repair fault: %w", num, tuple.Cnt, cntFields, err))
   425  				continue
   426  			}
   427  
   428  			repaired = true
   429  		}
   430  		{{- end }}
   431  
   432  		if tuple.Cnt < cntFields {
   433  			return nil, fmt.Errorf("not enought selected fields %d in response tuple: %d but expected %d fields", tuple.Cnt, num, cntFields)
   434  		}
   435  
   436  		np, err := TupleToStruct(ctx, tuple)
   437  		{{- if .Triggers.RepairTuple }}
   438  		if err != nil {
   439  			logger.Warn(ctx, "{{ $PublicStructName }}", fmt.Sprintf("error unpack tuple %s. Try to repair", err))
   440  
   441  			err = repairTuple(ctx, &tuple)
   442  			if err != nil {
   443  				logger.Error(ctx, "{{ $PublicStructName }}", fmt.Sprintf("can't repair: %s", err))
   444  				continue
   445  			}
   446  
   447  			repaired = true
   448  
   449  			np, err = TupleToStruct(ctx, tuple)
   450  		}
   451  		{{- end }}
   452  		if err != nil {
   453  			logger.Error(ctx, "{{ $PublicStructName }}", fmt.Sprintf("error unpack tuple %s", err))
   454  			return nil, err
   455  		}
   456  
   457  		np.BaseField.Repaired = repaired
   458  		ret = append(ret, np)
   459  	}
   460  
   461  	return ret, nil
   462  }
   463  {{ end -}}
   464  
   465  {{ range $ind, $fstruct := .FieldList -}}
   466  	{{ $packerparam := packerParam $fstruct.Format -}}
   467  	{{ $rtype := $fstruct.Format -}}
   468  	{{ $sname := $fstruct.Serializer.Name -}}
   469  	{{ if ne $sname "" -}}
   470  		{{ $serializer := index $serializers $sname -}}
   471  		{{ $rtype = $serializer.Type -}}
   472  func Marshal{{ $fstruct.Name }}({{ $fstruct.Name }} {{ $rtype }}) (any, error) {
   473      {{ $serparams := $fstruct.Serializer.Params -}}
   474      {{ $bvar :=  $packerparam.PackConvFunc $fstruct.Name -}}
   475      pvar, err := {{ $serializer.ImportName }}.{{ $serializer.Marshaler }}({{ $serparams }}{{ $bvar }})
   476      if err != nil {
   477          return nil, fmt.Errorf("error marshal field {{ $fstruct.Name }}: %w", err)
   478      }
   479  
   480      return pvar, nil
   481  }
   482  
   483  	{{ end -}}
   484  func pack{{ $fstruct.Name }}(w []byte, {{ $fstruct.Name }} {{ $rtype }}) ([]byte, error) {
   485  	{{ $bvar :=  $packerparam.PackConvFunc $fstruct.Name -}}
   486  	{{ if ne $sname "" -}}
   487  		{{ $serializer := index $serializers $sname -}}
   488  		{{ $serparams := $fstruct.Serializer.Params -}}
   489  	pvar, err := {{ $serializer.ImportName }}.{{ $serializer.Marshaler }}({{ $serparams }}{{ $bvar }})
   490  	if err != nil {
   491  		return nil, fmt.Errorf("error marshal field {{ $fstruct.Name }}: %w", err)
   492  	}
   493  	{{- else -}}
   494  	pvar := {{ $bvar }}
   495  	{{- end }}
   496  
   497  	return {{ $packerparam.PackFunc }}(w, pvar, iproto.ModeDefault), nil
   498  }
   499  
   500  func Unpack{{ $fstruct.Name }}(r *bytes.Reader) (ret {{ $rtype }}, errRet error) {
   501  	var {{ $fstruct.Name }} {{ if ne $packerparam.UnpackType "" }}{{ $packerparam.UnpackType }}{{ else }}{{ $fstruct.Format }}{{ end }}
   502  	{{ $isPointer := hasPrefix (printf "%s" $rtype) "*" }}
   503  
   504  	err := {{ $packerparam.UnpackFunc }}(r, &{{ $fstruct.Name }}, iproto.ModeDefault)
   505  	if err != nil {
   506  		errRet = fmt.Errorf("error unpack field {{ $fstruct.Name }} in tuple: '%w'", err)
   507  		return
   508  	}
   509  
   510  	bvar := {{ if ne $packerparam.UnpackConvFunc "" -}}
   511  		{{ $packerparam.UnpackConvFunc }}({{ $fstruct.Name }})
   512  	{{ else -}}
   513  		{{ $fstruct.Name }}
   514  	{{ end -}}
   515  
   516  	{{ $underlyingType := trimPrefix (printf "%s" $rtype) "*"}}
   517  	{{ if ne $sname "" -}}
   518  		{{ $serializer := index $serializers $sname -}}
   519  		{{ $serparams := $fstruct.Serializer.Params }}
   520  
   521  	var svar {{ $rtype }}
   522  	
   523  	err = {{ $serializer.ImportName }}.{{ $serializer.Unmarshaler }}({{ $serparams }}bvar, &svar)
   524  	if err != nil {
   525  		errRet = fmt.Errorf("error unmarshal field {{ $fstruct.Name }}: %w", err)
   526  		return
   527  	}
   528  
   529  	{{ else -}}
   530  	svar := bvar
   531  
   532  	{{ end -}}
   533  
   534  	return svar, nil
   535  }
   536  
   537  func (obj *{{ $PublicStructName }}) Get{{ $fstruct.Name }}() {{ $rtype }} {
   538  	return obj.field{{ $fstruct.Name }}
   539  }
   540  
   541  func (obj *{{ $PublicStructName }}) Set{{ $fstruct.Name }}({{ $fstruct.Name }} {{ $rtype }}) error {
   542  	{{- if $fstruct.PrimaryKey }}
   543  	if obj.BaseField.Exists {
   544  		return fmt.Errorf("can't modify field included in primary key")
   545  	}
   546  
   547  	{{ end -}}
   548  	data, err := pack{{ $fstruct.Name }}([]byte{}, {{ $fstruct.Name }})
   549  	if err != nil {
   550  		return err
   551  	}
   552  
   553  	{{- if eq $fstruct.Format "string" "[]byte" -}}
   554  		{{- if gt $fstruct.Size 0 }}
   555  
   556  	if len(data) > {{ $fstruct.Size }} {
   557  		return fmt.Errorf("max length of field '{{ $PublicStructName }}.{{ $fstruct.Name }}' is '%d' (received '%d')", {{ $fstruct.Size }}, len(data))
   558  	}
   559  		{{- else }}
   560  
   561  	logger := activerecord.Logger()
   562  
   563  	logger.Warn(context.TODO(), "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Size for field '{{ $fstruct.Name }}' not set. Cur field size: %d. Object: '{{ $PublicStructName }}'", len(data)))
   564  		{{- end }}
   565  	{{- end }}
   566  
   567  	obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, octopus.Ops{Field: {{ $ind }}, Op: octopus.OpSet, Value: data})
   568  
   569      {{- range $i, $mut := $fstruct.Mutators -}}
   570      {{ $customMutator := index $mutators $mut -}}
   571      {{ $pfLen := len $customMutator.PartialFields }}
   572      {{ if and (eq $pfLen 0) (ne $customMutator.Update "") }}
   573  	obj.BaseField.UpdateOps = []octopus.Ops{}
   574      data = octopus.PackLua("{{$customMutator.Update}}", obj.PrimaryString(), {{ $fstruct.Name}})
   575      obj.{{ $customMutator.Name }}.UpdateOps = append(obj.{{ $customMutator.Name }}.UpdateOps, octopus.Ops{Field: {{ $ind }}, Op: octopus.OpUpdate, Value: data})
   576  	{{ else if ne $pfLen 0 }}
   577  	{{ $isPointer := hasPrefix (printf "%s" $rtype) "*" }}
   578  	{{ if $isPointer }}
   579  	if {{ $fstruct.Name }} != nil {
   580  		{{- range $i, $pf := $customMutator.PartialFields }}
   581  		if obj.Set{{ $customMutator.Name }}{{ $pf.Name }}({{ $fstruct.Name }}.{{$pf.Name}}); err != nil {
   582  			return err
   583  		}
   584  		{{ end -}}
   585  	}
   586  	{{ else }}
   587  		{{- range $i, $pf := $customMutator.PartialFields }}
   588  		if obj.Set{{ $customMutator.Name }}{{ $pf.Name }}({{ $fstruct.Name }}.{{$pf.Name}}); err != nil {
   589  			return err
   590  		}
   591  		{{ end }}
   592  	{{ end }}
   593  	obj.field{{ $customMutator.Name }}Original = obj.field{{ $fstruct.Name }}
   594      {{ end }}
   595      {{ end }}
   596  	obj.field{{ $fstruct.Name }} = {{ $fstruct.Name}}
   597  
   598  	{{- if ne $fstruct.ObjectLink "" }}
   599  	delete(obj.BaseField.Objects, "{{ $fstruct.ObjectLink }}")
   600  	{{- end }}
   601  
   602  	return nil
   603  }
   604  	{{ range $i, $mut := $fstruct.Mutators -}}
   605      {{ $customMutator := index $mutators $mut -}}
   606      {{ $pfLen := len $customMutator.PartialFields }}
   607  	{{- if $customMutator.Name }}
   608  
   609      {{ if ne $pfLen 0 }}
   610  func (obj *{{ $PublicStructName }}) pack{{ $fstruct.Name }}PartialFields(op octopus.OpCode) error {
   611      pfs := obj.Mutators.{{ $customMutator.Name }}.PartialFields
   612  	if len(pfs) == 0 {
   613  		return nil
   614  	}
   615  
   616      var (
   617              mutatorArgs []string
   618              err error
   619          )
   620  
   621  	switch op {
   622      {{ if ne $customMutator.Update "" -}}
   623      case octopus.OpUpdate:
   624          mutatorArgs, err = {{ $customMutator.ImportName }}.{{ $PublicStructName }}{{ $customMutator.Name }}Update(obj.field{{ $customMutator.Name }}Original, pfs)
   625      {{ end }}
   626      {{ if ne $customMutator.Replace "" -}}
   627      case octopus.OpInsert:
   628          mutatorArgs, err = {{ $customMutator.ImportName }}.{{ $PublicStructName }}{{ $customMutator.Name }}Replace(obj.field{{ $customMutator.Name }}Original, pfs)
   629      {{ end }}
   630  	}
   631  
   632  	if err != nil {
   633  		return err
   634  	}
   635  
   636      data := octopus.PackLua(obj.Mutators.{{ $customMutator.Name }}.OpFunc[op], append([]string{obj.PrimaryString()}, mutatorArgs...)...)
   637  
   638  	{{- if eq $fstruct.Format "string" "[]byte" -}}
   639  		{{- if gt $fstruct.Size 0 }}
   640  
   641  	if len(data) > {{ $fstruct.Size }} {
   642  		return fmt.Errorf("max length of field '{{ $PublicStructName }}.{{ $fstruct.Name }}' is '%d' (received '%d')", {{ $fstruct.Size }}, len(data))
   643  	}
   644  		{{- else }}
   645  
   646  	logger := activerecord.Logger()
   647  
   648  	logger.Warn(context.TODO(), "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Size for field '{{ $fstruct.Name }}' not set. Cur field size: %d. Object: '{{ $PublicStructName }}'", len(data)))
   649  		{{- end }}
   650  	{{- end }}
   651  
   652  	obj.{{ $customMutator.Name }}.UpdateOps = []octopus.Ops{}
   653  
   654      obj.{{ $customMutator.Name }}.UpdateOps = append(obj.{{ $customMutator.Name }}.UpdateOps, octopus.Ops{Field: {{ $ind }}, Op: octopus.OpUpdate, Value: data})
   655  
   656      return nil
   657  }
   658          {{ end }}
   659  
   660  	    {{ range $i, $f := $customMutator.PartialFields }}
   661  
   662  func (obj *{{ $PublicStructName }}) Set{{ $customMutator.Name }}{{ $f.Name }}({{ $f.Name }} {{ $f.Type }}) error {
   663      obj.Mutators.{{ $customMutator.Name }}.PartialFields["{{ $f.Name }}"] = {{ $f.Name }}
   664  
   665  	if err := obj.pack{{ $fstruct.Name }}PartialFields(octopus.OpUpdate); err != nil {
   666  		return fmt.Errorf("pack {{ $customMutator.Name }}{{ $f.Name }}: %w", err)
   667  	}
   668  
   669      return nil
   670  }
   671          {{ end }}
   672  	{{else}}
   673  		{{ $mutatorparam := mutatorParam $mut $fstruct.Format -}}
   674  		{{ $mtype := $fstruct.Format }}
   675  
   676  func (obj *{{ $PublicStructName }}) {{ $mutatorparam.Name }}{{ $fstruct.Name }}(mutArg {{ $mtype }}) error {
   677  		{{- if eq $mutatorparam.Name "Inc" }}
   678  	if mutArg == 0 {
   679  		return nil
   680  	}
   681  
   682  	if uint64({{ $packerparam.MaxValue }} - obj.field{{ $fstruct.Name }}) < uint64(mutArg) {
   683  		return fmt.Errorf("overflow type '{{ $fstruct.Format }}' after Inc %d", mutArg)
   684  	}
   685  
   686  	data := iproto.PackUint32([]byte{}, uint32(mutArg), iproto.ModeDefault)
   687  
   688  	obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, octopus.Ops{Field: {{ $ind }}, Op: octopus.OpAdd, Value: data})
   689  	obj.field{{ $fstruct.Name }} += {{ $packerparam.MutatorTypeConv }}(mutArg)
   690  		{{- else if eq $mutatorparam.Name "Dec" }}
   691  	if mutArg == 0 {
   692  		return nil
   693  	}
   694  
   695  	if uint64(obj.field{{ $fstruct.Name }} - {{ $packerparam.MinValue }}) < uint64(mutArg) {
   696  		return fmt.Errorf("overflow type '{{ $fstruct.Format }}' after Dec %d", mutArg)
   697  	}
   698  
   699  	data := iproto.PackUint32([]byte{}, uint32(-mutArg), iproto.ModeDefault)
   700  
   701  	obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, octopus.Ops{Field: {{ $ind }}, Op: octopus.OpAdd, Value: data})
   702  	obj.field{{ $fstruct.Name }} -= {{ $packerparam.MutatorTypeConv }}(mutArg)
   703  		{{- else if eq $mutatorparam.Name "And" }}
   704  	if obj.field{{ $fstruct.Name }} == 0 || obj.field{{ $fstruct.Name }} & mutArg == obj.field{{ $fstruct.Name }} {
   705  		return nil
   706  	}
   707  
   708  	data := iproto.PackUint32([]byte{}, uint32(mutArg), iproto.ModeDefault)
   709  
   710  	obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, octopus.Ops{Field: {{ $ind }}, Op: octopus.OpAnd, Value: data})
   711  	obj.field{{ $fstruct.Name }} &= mutArg
   712  		{{- else if eq $mutatorparam.Name "Or" "SetBit" }}
   713  	if mutArg == 0 || obj.field{{ $fstruct.Name }} | mutArg == obj.field{{ $fstruct.Name }} {
   714  		return nil
   715  	}
   716  
   717  	data := iproto.PackUint32([]byte{}, uint32(mutArg), iproto.ModeDefault)
   718  
   719  	obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, octopus.Ops{Field: {{ $ind }}, Op: octopus.OpOr, Value: data})
   720  	obj.field{{ $fstruct.Name }} |= mutArg
   721  		{{- else if eq $mutatorparam.Name "ClearBit" }}
   722  	if mutArg == 0 || obj.field{{ $fstruct.Name }} & ^mutArg == obj.field{{ $fstruct.Name }} {
   723  		return nil
   724  	}
   725  
   726  	data := iproto.PackUint32([]byte{}, uint32(^mutArg), iproto.ModeDefault)
   727  
   728  	obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, octopus.Ops{Field: {{ $ind }}, Op: octopus.OpAnd, Value: data})
   729  	obj.field{{ $fstruct.Name }} &= ^mutArg
   730  		{{- else if eq $mutatorparam.Name "Xor" }}
   731  	if mutArg == 0 || obj.field{{ $fstruct.Name }} ^ mutArg == obj.field{{ $fstruct.Name }} {
   732  		return nil
   733  	}
   734  
   735  	data := iproto.PackUint32([]byte{}, uint32(mutArg), iproto.ModeDefault)
   736  
   737  	obj.BaseField.UpdateOps = append(obj.BaseField.UpdateOps, octopus.Ops{Field: {{ $ind }}, Op: octopus.OpXor, Value: data})
   738  	obj.field{{ $fstruct.Name }} ^= mutArg
   739  		{{- else }}
   740  	Unknown mutator type in template!!!
   741  		{{- end }}
   742  
   743  	return nil
   744  }
   745  	{{- end }}
   746  	{{- end }}
   747  	{{- $fl := index $flags $fstruct.Name }}
   748  	{{- if $fl }}
   749  		{{- range $i, $flag := $fl.Flags }}
   750  
   751  func (obj *{{ $PublicStructName }}) Set{{ $fstruct.Name }}{{ $flag }}() error {
   752  	return obj.SetBit{{ $fstruct.Name }}( {{ $fstruct.Name }}{{ $flag }}Flag )
   753  }
   754  
   755  func (obj *{{ $PublicStructName }}) Clear{{ $fstruct.Name }}{{ $flag }}() error {
   756  	return obj.ClearBit{{ $fstruct.Name }}( {{ $fstruct.Name }}{{ $flag }}Flag )
   757  }
   758  
   759  func (obj *{{ $PublicStructName }}) Is{{ $fstruct.Name }}{{ $flag }}() bool {
   760  	return obj.Get{{ $fstruct.Name }}() & {{ $fstruct.Name }}{{ $flag }}Flag == {{ $fstruct.Name }}{{ $flag }}Flag
   761  }
   762  		{{- end }}
   763  	{{- end }}
   764  
   765  {{ end -}}
   766  
   767  {{ if $fields }}
   768  func selectBox (ctx context.Context, indexnum uint32, keysPacked [][][]byte, limiter activerecord.SelectorLimiter) ([]*{{ $PublicStructName }}, error) {
   769  	logger := activerecord.Logger()
   770  	ctx = logger.SetLoggerValueToContext(ctx, activerecord.ValueLogPrefix{"limiter": limiter.String()})
   771  	metricTimer := activerecord.Metric().Timer("octopus", "{{ $PublicStructName }}")
   772  	metricStatCnt := activerecord.Metric().StatCount("octopus", "{{ $PublicStructName }}")
   773  	metricErrCnt := activerecord.Metric().ErrorCount("octopus", "{{ $PublicStructName }}")
   774  
   775  	w := octopus.PackSelect(namespace, indexnum, limiter.Offset(), limiter.Limit(), keysPacked)
   776  
   777  	metricTimer.Timing(ctx, "select_pack")
   778  	metricStatCnt.Inc(ctx, "select_keys", float64(len(keysPacked)))
   779  
   780  	logger.Debug(ctx, fmt.Sprintf("Select packed tuple: '% X'", w))
   781  
   782  	connection, err := octopus.Box(ctx, 0, activerecord.ReplicaOrMasterInstanceType, "arcfg", nil)
   783  	if err != nil {
   784  		metricErrCnt.Inc(ctx, "select_preparebox", 1)
   785  		logger.Error(ctx, fmt.Sprintf("Error get box '%s'", err))
   786  
   787  		return nil, err
   788  	}
   789  
   790  	respBytes, errCall := connection.Call(ctx, octopus.RequestTypeSelect, w)
   791  	if errCall != nil {
   792  		metricErrCnt.Inc(ctx, "select_box", 1)
   793  		logger.Error(ctx, "Error select from box", errCall, connection.Info())
   794  
   795  		return nil, errCall
   796  	}
   797  
   798  	metricTimer.Timing(ctx, "select_box")
   799  
   800  	logger.Debug(ctx, fmt.Sprintf("Response from box '%X'", respBytes))
   801  
   802  	tuplesData, err := octopus.ProcessResp(respBytes, 0)
   803  	if err != nil {
   804  		metricErrCnt.Inc(ctx, "select_resp", 1)
   805  		logger.Error(ctx, "Error parse response: ", err)
   806  
   807  		return nil, err
   808  	}
   809  
   810  	metricTimer.Timing(ctx, "select_process")
   811  	metricStatCnt.Inc(ctx, "select_tuples_res", float64(len(tuplesData)))
   812  
   813  	nps, err := NewFromBox(ctx, tuplesData)
   814  	if err != nil {
   815  		metricErrCnt.Inc(ctx, "select_preparebox", 1)
   816  		logger.Error(ctx, "Error in response: ", err)
   817  
   818  		return nil, err
   819  	}
   820  
   821  	metricTimer.Timing(ctx, "select_newobj")
   822  
   823  	if limiter.FullfillWarn() && len(nps) == int(limiter.Limit()) {
   824  		logger.Warn(ctx, "Select limit reached. Result may less than db records.")
   825  	}
   826  
   827  	mode, ok := connection.InstanceMode().(activerecord.ServerModeType)
   828  	if !ok || mode == activerecord.ModeReplica {
   829  		if !ok {
   830  			logger.Error(ctx, "Invalid server mode type: %T", connection.InstanceMode())
   831  		}
   832  
   833  		for npNum := range nps {
   834  			nps[npNum].IsReplica = true
   835  			nps[npNum].Readonly = true
   836  		}
   837  	}
   838  
   839  	logger.Debug(ctx, "Success select")
   840  
   841  	metricTimer.Finish(ctx, "select")
   842  
   843  	return nps, nil
   844  }
   845  {{ end }}
   846  
   847  {{ if $fields }} // indexes
   848  {{ $pktype := "" }}
   849  {{ $pklenfld := 1 }}
   850  {{ $pkind := index .Indexes 0 }}
   851  {{ range $num, $ind := .Indexes -}}
   852  {{ $lenfld := len $ind.Fields -}}
   853  	{{ if $ind.Primary }}
   854  		{{ $pktype = $ind.Type }}
   855  		{{ $pklenfld = len $ind.Fields }}
   856  		{{ $pkind = $ind }}
   857  func (obj *{{ $PublicStructName }}) Primary() {{ $ind.Type }} {
   858  		{{ if ne $lenfld 1 }}
   859  	return {{ $ind.Type }}{
   860  			{{- range $_, $fieldNum := $ind.Fields }}
   861  				{{- $ifield := index $fields $fieldNum }}
   862  		{{ $ifield.Name }}: obj.Get{{ $ifield.Name }}(),
   863  			{{- end }}
   864  	}
   865  		{{ else }}
   866  			{{- range $_, $fieldNum := $ind.Fields }}
   867  				{{- $ifield := index $fields $fieldNum }}
   868  	return obj.Get{{ $ifield.Name }}()
   869  			{{- end }}
   870  		{{ end -}}
   871  }
   872  
   873  func SelectByPrimary(ctx context.Context, pk {{ $ind.Type }}) (*{{ $PublicStructName }}, error) {
   874  	return {{ $ind.Selector }}(ctx, pk)
   875  }
   876  	{{ end }}
   877  {{ end }}
   878  
   879  {{ range $num, $ind := .Indexes -}}
   880  	{{ $lenfld := len $ind.Fields -}}
   881  	{{ if ne $lenfld 1 }}
   882  type {{ $ind.Type }} struct {
   883  		{{- range $_, $fieldNum := $ind.Fields }}
   884  			{{- $ifield := index $fields $fieldNum }}
   885  	{{ $rtype := $ifield.Format -}}
   886  	{{ $serlen := len $ifield.Serializer -}}
   887  	{{ if ne $serlen 0 -}}
   888  		{{ $sname := index $ifield.Serializer 0 -}}
   889  		{{ $serializer := index $serializers $sname -}}
   890  		{{ $rtype = $serializer.Type -}}
   891  	{{ end }}
   892  	{{ $ifield.Name }} {{ $rtype -}}
   893  		{{- end }}
   894  }
   895  	{{ end -}}
   896  
   897  func PackKeyIndex{{ $ind.Name }}(ctx context.Context, keys []{{ $ind.Type }}) ([][][]byte, error) {
   898  	keysPacked := [][][]byte{}
   899  
   900  	for _, key := range keys {
   901  		keysField := [][]byte{}
   902  		{{ if ne $lenfld 1 -}}
   903  			{{ range $numf, $ifld := $ind.Fields -}}
   904  				{{ $sfield := index $fields $ifld -}}
   905  				{{ $packerparam := packerParam $sfield.Format -}}
   906  				{{ $packparam := printf "key.%s" $sfield.Name -}}
   907  				{{ $serlen := len $sfield.Serializer }}
   908  				{{ if ne $serlen 0 }}
   909  					{{ $sname := index $sfield.Serializer 0 -}}
   910  					{{ $serializer := index $serializers $sname -}}
   911  					{{ $serparams := $sfield.Serializer.Params -}}
   912  					skey, err := {{ $serializer.ImportName }}.{{ $serializer.Marshaler }}({{ $serparams }}{{ $packparam }})
   913  					if err != nil {
   914  						return nil, err
   915  					}
   916  					{{ $packparam = "skey" }}
   917  				{{ end }}
   918  
   919  		keysField = append(keysField, {{ $packerparam.PackFunc }}([]byte{}, {{ $packerparam.PackConvFunc $packparam }}, iproto.ModeDefault))
   920  			{{ end -}}
   921  		{{ else -}}
   922  			{{ $ifield := index $ind.Fields 0 -}}
   923  			{{ $sfield := index $fields $ifield -}}
   924  			{{ $packerparam := packerParam $sfield.Format -}}
   925  		keysField = append(keysField, {{ $packerparam.PackFunc }}([]byte{}, {{ $packerparam.PackConvFunc "key" }}, iproto.ModeDefault))
   926  		{{ end -}}
   927  		keysPacked = append(keysPacked, keysField)
   928  	}
   929  
   930  	return keysPacked, nil
   931  }
   932  func UnpackKeyIndex{{ $ind.Name }}(packedKeys [][][]byte) ([]{{ $ind.Type }}, error) {
   933  	ret := []{{ $ind.Type }}{}
   934  
   935  	for _, packedKey := range packedKeys {
   936  		{{ if ne $lenfld 1 }}
   937  		newIField := {{ $ind.Type }}{}
   938  		
   939  		var err error
   940  
   941  		{{- range $num, $fieldNum := $ind.Fields }}
   942  			{{- $ifield := index $fields $fieldNum }}
   943  			newIField.{{ $ifield.Name }}, err = Unpack{{ $ifield.Name }}(bytes.NewReader(packedKey[{{$num}}]))
   944  			if err != nil {
   945  				return nil, fmt.Errorf("can't unpack index: %s", err)
   946  			}
   947  		{{ end }}
   948  		{{ else }}
   949  		{{- $fieldNum := index $ind.Fields 0 }}
   950  		{{- $ifield := index $fields $fieldNum }}
   951  		newIField, err := Unpack{{ $ifield.Name }}(bytes.NewReader(packedKey[0]))
   952  		if err != nil {
   953  			return nil, fmt.Errorf("can't unpack index: %s", err)
   954  		}
   955  		{{ end }}
   956  		ret = append(ret, newIField)
   957  	}
   958  
   959  	return ret, nil
   960  }
   961  /*
   962  
   963  	keysPacked := [][][]byte{}
   964  
   965  	for _, key := range keys {
   966  		keysField := [][]byte{}
   967  		{{ if ne $lenfld 1 -}}
   968  			{{ range $numf, $ifld := $ind.Fields -}}
   969  				{{ $sfield := index $fields $ifld -}}
   970  				{{ $packerparam := packerParam $sfield.Format -}}
   971  				{{ $packparam := printf "key.%s" $sfield.Name -}}
   972  				{{ $serlen := len $sfield.Serializer }}
   973  				{{ if ne $serlen 0 }}
   974  					{{ $sname := index $sfield.Serializer 0 -}}
   975  					{{ $serializer := index $serializers $sname -}}
   976  					{{ $serparams := $sfield.Serializer.Params -}}
   977  					skey, err := {{ $serializer.ImportName }}.{{ $serializer.Marshaler }}({{ $serparams }}{{ $packparam }})
   978  					if err != nil {
   979  						return nil, err
   980  					}
   981  					{{ $packparam = "skey" }}
   982  				{{ end }}
   983  
   984  		keysField = append(keysField, {{ $packerparam.PackFunc }}([]byte{}, {{ $packerparam.PackConvFunc $packparam }}, iproto.ModeDefault))
   985  			{{ end -}}
   986  		{{ else -}}
   987  			{{ $ifield := index $ind.Fields 0 -}}
   988  			{{ $sfield := index $fields $ifield -}}
   989  			{{ $packerparam := packerParam $sfield.Format -}}
   990  		keysField = append(keysField, {{ $packerparam.PackFunc }}([]byte{}, {{ $packerparam.PackConvFunc "key" }}, iproto.ModeDefault))
   991  		{{ end -}}
   992  		keysPacked = append(keysPacked, keysField)
   993  	}
   994  
   995  	return keysPacked, nil
   996  }
   997  */
   998  func {{ $ind.Selector }}s(ctx context.Context, keys []{{ $ind.Type }}{{ if not $ind.Unique }}, limiter activerecord.SelectorLimiter{{ end }}) ([]*{{ $PublicStructName }}, error) {
   999  	ctx = activerecord.Logger().SetLoggerValueToContext(ctx, map[string]interface{}{"{{ $ind.Selector }}s": keys, "Repo": "{{ $PublicStructName }}" })
  1000  
  1001  	keysPacked, err := PackKeyIndex{{ $ind.Name }}(ctx, keys)
  1002  	if err != nil {
  1003  		return nil, fmt.Errorf("can't pack index key: %s", err)
  1004  	}
  1005  
  1006  	{{ if $ind.Unique -}}
  1007  	limiter := activerecord.EmptyLimiter()
  1008  	{{ end }}
  1009  
  1010  	res, err := selectBox(ctx, {{ $ind.Num }}, keysPacked, limiter)
  1011  	if err != nil {
  1012  		return res, err	
  1013  	}
  1014  
  1015  	activerecord.Logger().CollectQueries(ctx, {{ $ind.Selector }}MockerLogger(keys, {{ $PublicStructName }}List(res){{ if not $ind.Unique }}, limiter {{ end }}))
  1016  
  1017  	return res, err
  1018  }
  1019  
  1020  func {{ $ind.Selector }}(ctx context.Context, key {{ $ind.Type }}{{ if not $ind.Unique }}, limiter activerecord.SelectorLimiter{{ end }}) ({{ if $ind.Unique }}{{ else }}[]{{ end }}*{{ $PublicStructName }}, error) {
  1021  	selected, err := {{ $ind.Selector }}s(ctx, []{{ $ind.Type }}{key}{{ if not $ind.Unique }}, limiter{{ end }})
  1022  	if err != nil {
  1023  		return nil, err
  1024  	}
  1025  
  1026  	{{ if $ind.Unique -}}
  1027  	if len(selected) > 0 {
  1028  		if len(selected) > 1 {
  1029  			activerecord.Logger().Error(ctx, "{{ $PublicStructName }}", "More than one tuple for uniq key ID '%s': %d", key, len(selected))
  1030  		}
  1031  
  1032  		return selected[0], nil
  1033  	}
  1034  
  1035  	return nil, nil
  1036  	{{- else }}
  1037  
  1038  	return selected, nil
  1039  	{{- end }}
  1040  }
  1041  {{ end }}
  1042  {{ end }}// end indexes
  1043  {{ range $name, $fobj := .FieldObject -}}
  1044  {{ $linkedobj := index $LinkedObject $fobj.ObjectName }}
  1045  func (obj *{{ $PublicStructName }}) Get{{ $name }}(ctx context.Context) ({{ if not $fobj.Unique }}[]{{ end }}*{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }}, error){
  1046  	{{- if $fobj.Unique }}
  1047  	if ret, ok := obj.BaseField.Objects["{{ $name }}"]; ok && len(ret) == 1 {
  1048  		return ret[0].(*{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }}), nil
  1049  	}
  1050  
  1051  	ret, err := {{ $linkedobj.Namespace.PackageName }}.SelectBy{{ $fobj.Key }}(ctx, obj.Get{{ $fobj.Field }}())
  1052  	if err != nil {
  1053  		return nil, err
  1054  	}
  1055  
  1056  	obj.BaseField.Objects["{{ $name }}"] = []octopus.ModelStruct{ret}
  1057  	{{- else }}
  1058  
  1059  	var ret []*{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }}
  1060  
  1061  	if retI, ok := obj.BaseField.Objects["{{ $name }}"]; ok && len(retI) > 0 {
  1062  		for _, ri := range retI {
  1063  			ret = append(ret, ri.(*{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }}))
  1064  		}
  1065  
  1066  		return ret, nil
  1067  	}
  1068  
  1069  	ret, err := {{ $linkedobj.Namespace.PackageName }}.SelectBy{{ $fobj.Key }}(ctx, obj.Get{{ $fobj.Field }}(), activerecord.NewLimiter(100)) //ToDo default limit for multi object
  1070  	if err != nil {
  1071  		return nil, err
  1072  	}
  1073  
  1074  	if len(ret) == 100 {
  1075  		activerecord.Logger().Warn(ctx, "limit for multiple linked object riched '{{ $linkedobj.Namespace.PackageName }}.{{ $linkedobj.Namespace.PublicName }}' '{{ $PublicStructName }}'")
  1076  	}
  1077  
  1078  	for _, r := range ret {
  1079  		obj.BaseField.Objects["{{ $name }}"] = append(obj.BaseField.Objects["{{ $name }}"], r)
  1080  	}
  1081  	{{- end }}
  1082  
  1083  	return ret, nil
  1084  }
  1085  
  1086  {{ end -}}
  1087  
  1088  {{ if $fields }}
  1089  func (obj *{{ $PublicStructName }}) Equal (anotherObjI any) bool {
  1090  	anotherObj, ok := anotherObjI.(*{{ $PublicStructName }})
  1091  	if !ok {
  1092  		return false
  1093  	}
  1094  
  1095  	var dataObj []byte
  1096  	var dataAnotherObj []byte
  1097  	var err error
  1098  
  1099  	{{- range $ind, $fstruct := .FieldList }} 
  1100  	dataObj, err = pack{{ $fstruct.Name }}([]byte{}, obj.Get{{ $fstruct.Name }}())
  1101  	if err != nil {
  1102  		return false
  1103  	}
  1104  
  1105  	dataAnotherObj, err = pack{{ $fstruct.Name }}([]byte{}, anotherObj.Get{{ $fstruct.Name }}())
  1106  	if err != nil {
  1107  		return false
  1108  	}
  1109  
  1110  	if string(dataObj) != string(dataAnotherObj) {
  1111  		return false
  1112  	}
  1113  	{{ end }}
  1114  
  1115  	return true
  1116  }
  1117  
  1118  func (obj *{{ $PublicStructName }}) PrimaryString() string {
  1119  	ret := []string{
  1120  	{{- range $ind, $fstruct := .FieldList }}
  1121  		{{- if $fstruct.PrimaryKey }}
  1122  			{{- $packerparam := packerParam $fstruct.Format }}
  1123  			{{- $tostr := $packerparam.ToString }} 
  1124  			{{ index $tostr 0 }}obj.Get{{ $fstruct.Name }}(){{ index $tostr 1 }},
  1125  		{{- end }}
  1126  	{{- end }}
  1127  	}
  1128  
  1129  	return strings.Join(ret, ", ")
  1130  }
  1131  
  1132  {{ $pktype := "" }}
  1133  {{ $pklenfld := 1 }}
  1134  {{ $pkind := index .Indexes 0 }}
  1135  {{ range $num, $ind := .Indexes -}}
  1136  {{ $lenfld := len $ind.Fields -}}
  1137  	{{ if $ind.Primary }}
  1138  		{{ $pktype = $ind.Type }}
  1139  		{{ $pklenfld = len $ind.Fields }}
  1140  		{{ $pkind = $ind }}
  1141  func (obj *{{ $PublicStructName }}) packPk() ([][]byte, error) {
  1142  	packedPk := [][]byte{}
  1143  
  1144  	var (
  1145  		data []byte
  1146  		err error
  1147  	)
  1148  		{{ if ne $lenfld 1 }}
  1149  			{{- range $_, $fieldNum := $ind.Fields }}
  1150  				{{- $ifield := index $fields $fieldNum }}
  1151  
  1152  					data, err = pack{{ $ifield.Name }}([]byte{}, obj.Get{{ $ifield.Name }}())
  1153                  	if err != nil {
  1154                  		return [][]byte{}, err
  1155                  	}
  1156  
  1157                  	packedPk = append(packedPk, data)
  1158  			{{- end }}
  1159  		{{ else }}
  1160  			{{- range $_, $fieldNum := $ind.Fields }}
  1161  				{{- $ifield := index $fields $fieldNum }}
  1162  
  1163  					data, err = pack{{ $ifield.Name }}([]byte{}, obj.Get{{ $ifield.Name }}())
  1164                  	if err != nil {
  1165                  		return [][]byte{}, err
  1166                  	}
  1167  
  1168                  	packedPk = append(packedPk, data)
  1169  			{{- end }}
  1170  		{{ end }}
  1171  
  1172  		return packedPk, nil
  1173  }
  1174  	{{ end }}
  1175  {{ end }}
  1176  
  1177  func (obj *{{ $PublicStructName }}) Delete(ctx context.Context) error {
  1178  	logger := activerecord.Logger()
  1179  	metricTimer := activerecord.Metric().Timer("octopus", "{{ $PublicStructName }}")
  1180  	metricStatCnt := activerecord.Metric().StatCount("octopus", "{{ $PublicStructName }}")
  1181  	metricErrCnt := activerecord.Metric().ErrorCount("octopus", "{{ $PublicStructName }}")
  1182  
  1183  	metricStatCnt.Inc(ctx, "delete_request", 1)
  1184  
  1185  	if !obj.BaseField.Exists {
  1186  		return fmt.Errorf("can't delete not exists object")
  1187  	}
  1188  
  1189  	pk, err := obj.packPk()
  1190  	if err != nil {
  1191  		metricErrCnt.Inc(ctx, "delete_pack", 1)
  1192  		return fmt.Errorf("error delete: %w", err)
  1193  	}
  1194  
  1195  	w := octopus.PackDelete(namespace, pk)
  1196  	log.Printf("Delete packed tuple: '%X'\n", w)
  1197  
  1198  	connection, err := octopus.Box(ctx, 0, activerecord.MasterInstanceType, "arcfg", nil)
  1199  	if err != nil {
  1200  		metricErrCnt.Inc(ctx, "delete_preparebox", 1)
  1201  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Error get box '%s'", err))
  1202  
  1203  		return err
  1204  	}
  1205  
  1206  	respBytes, errCall := connection.Call(ctx, octopus.RequestTypeDelete, w)
  1207  	if errCall != nil {
  1208  		metricErrCnt.Inc(ctx, "delete_box", 1)
  1209  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error delete from box", errCall, connection.Info())
  1210  		
  1211  		return errCall
  1212  	}
  1213  
  1214  	metricTimer.Timing(ctx, "delete_box")
  1215  
  1216  	logger.Debug(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Response from box '% X'", respBytes))
  1217  
  1218  	_, err = octopus.ProcessResp(respBytes, octopus.NeedRespFlag|octopus.UniqRespFlag)
  1219  	if err != nil {
  1220  		metricErrCnt.Inc(ctx, "delete_resp", 1)
  1221  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error parse response: ", err)
  1222  		
  1223  		return err
  1224  	}
  1225  
  1226  	metricStatCnt.Inc(ctx, "delete_success", 1)
  1227  
  1228  	obj.BaseField.Exists = false
  1229  	obj.BaseField.UpdateOps = []octopus.Ops{}
  1230  
  1231  	logger.Debug(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Success delete")
  1232  
  1233  	metricTimer.Finish(ctx, "delete")
  1234  
  1235  	return nil
  1236  }
  1237  
  1238  func (obj *{{ $PublicStructName }}) Update(ctx context.Context) error {
  1239  	logger := activerecord.Logger()
  1240  	metricTimer := activerecord.Metric().Timer("octopus", "{{ $PublicStructName }}")
  1241  	metricStatCnt := activerecord.Metric().StatCount("octopus", "{{ $PublicStructName }}")
  1242  	metricErrCnt := activerecord.Metric().ErrorCount("octopus", "{{ $PublicStructName }}")
  1243  
  1244  	metricStatCnt.Inc(ctx, "update_request", 1)
  1245  
  1246  	if !obj.BaseField.Exists {
  1247  		metricErrCnt.Inc(ctx, "update_notexists", 1)
  1248  		return fmt.Errorf("can't update not exists object")
  1249  	}
  1250  
  1251  	if obj.BaseField.Repaired {
  1252  		metricStatCnt.Inc(ctx, "update_repaired", 1)
  1253  		logger.Debug(ctx, "", obj.PrimaryString(), "Flag 'Repaired' is true! Insert instead Update")
  1254  
  1255  		return obj.Replace(ctx)
  1256  	}
  1257  
  1258  	connection, err := octopus.Box(ctx, 0, activerecord.MasterInstanceType, "arcfg", nil)
  1259  	if err != nil {
  1260  		metricErrCnt.Inc(ctx, "update_preparebox", 1)
  1261  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Error get box '%s'", err))
  1262  		return err
  1263  	}
  1264  
  1265  {{if eq $mutatorLen 0}}
  1266  	if len(obj.BaseField.UpdateOps) == 0 {
  1267  		metricStatCnt.Inc(ctx, "update_empty", 1)
  1268  		logger.Debug(ctx, "", obj.PrimaryString(), "Empty update")
  1269  
  1270  		return nil
  1271  	}
  1272  {{else}}
  1273  	if len(obj.BaseField.UpdateOps) > 0 {
  1274  {{- end }}
  1275  	pk, err := obj.packPk()
  1276  	if err != nil {
  1277  		metricErrCnt.Inc(ctx, "update_packpk", 1)
  1278  		return fmt.Errorf("error update: %w", err)
  1279  	}
  1280  
  1281  	w := octopus.PackUpdate(namespace, pk, obj.BaseField.UpdateOps)
  1282  
  1283  	log.Printf("Update packed tuple: '%X'\n", w)
  1284  
  1285  	respBytes, errCall := connection.Call(ctx, octopus.RequestTypeUpdate, w)
  1286  	if errCall != nil {
  1287  		metricErrCnt.Inc(ctx, "update_box", 1)
  1288  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error update ia a box", errCall, connection.Info())
  1289  		return errCall
  1290  	}
  1291  
  1292  	metricTimer.Timing(ctx, "update_box")
  1293  
  1294  	logger.Debug(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Response from box '%X'", respBytes))
  1295  
  1296  	_, err = octopus.ProcessResp(respBytes, octopus.NeedRespFlag|octopus.UniqRespFlag)
  1297  	if err != nil {
  1298  		metricErrCnt.Inc(ctx, "update_resp", 1)
  1299  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error parse response: ", err)
  1300  		return err
  1301  	}
  1302  
  1303  {{if gt $mutatorLen 0}}
  1304  	}
  1305  {{end}}
  1306  {{if gt $mutatorLen 0}}
  1307  {{ range $ind, $fstruct := .FieldList -}}
  1308  	{{- range $i, $mut := $fstruct.Mutators -}}
  1309  		{{ $customMutator := index $mutators $mut -}}
  1310  		{{ $pfLen := len $customMutator.PartialFields }}
  1311  		{{ if and (ne $pfLen 0) (ne $customMutator.Update "") $customMutator.Name }}
  1312  	for _, op := range obj.{{$customMutator.Name}}.UpdateOps {
  1313  		resp, errCall := connection.Call(ctx, octopus.RequestTypeCall, op.Value)
  1314  		if errCall != nil {
  1315  			metricErrCnt.Inc(ctx, "call_proc", 1)
  1316  			logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error call proc in a box", errCall, connection.Info())
  1317  			return errCall
  1318  		}
  1319  
  1320  		_, err := octopus.ProcessResp(resp, 0)
  1321  		if err != nil {
  1322  			return fmt.Errorf("error unpack lua response: %w", err)
  1323  		}
  1324  	}
  1325  
  1326  	obj.{{$customMutator.Name}}.UpdateOps = []octopus.Ops{}
  1327  	obj.{{$customMutator.Name}}.PartialFields = map[string]any{}
  1328  		{{end}}
  1329  	{{end}}
  1330  {{end}}
  1331  {{end}}
  1332  
  1333  	obj.BaseField.UpdateOps = []octopus.Ops{}
  1334  
  1335  	logger.Debug(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Success update")
  1336  
  1337  	metricStatCnt.Inc(ctx, "update_success", 1)
  1338  	metricTimer.Finish(ctx, "update")
  1339  
  1340  	return nil
  1341  }
  1342  
  1343  func (obj *{{ $PublicStructName }}) Insert(ctx context.Context) error {
  1344  	metricStatCnt := activerecord.Metric().StatCount("octopus", "{{ $PublicStructName }}")
  1345  	metricErrCnt := activerecord.Metric().ErrorCount("octopus", "{{ $PublicStructName }}")
  1346  
  1347  	metricStatCnt.Inc(ctx, "insert_request", 1)
  1348  
  1349  	if obj.BaseField.Exists {
  1350  		metricErrCnt.Inc(ctx, "insert_exists", 1)
  1351  		return fmt.Errorf("can't insert already exists object")
  1352  	}
  1353  
  1354  	err := obj.insertReplace(ctx, octopus.InsertModeInsert)
  1355  
  1356  	if err == nil {
  1357  		metricStatCnt.Inc(ctx, "insert_success", 1)
  1358  	}
  1359  
  1360  	return err
  1361  }
  1362  
  1363  func (obj *{{ $PublicStructName }}) Replace(ctx context.Context) error {
  1364  	metricStatCnt := activerecord.Metric().StatCount("octopus", "{{ $PublicStructName }}")
  1365  	metricErrCnt := activerecord.Metric().ErrorCount("octopus", "{{ $PublicStructName }}")
  1366  
  1367  	metricStatCnt.Inc(ctx, "replace_request", 1)
  1368  
  1369  	if !obj.BaseField.Exists {
  1370  		metricErrCnt.Inc(ctx, "replace_notexists", 1)
  1371  		return fmt.Errorf("can't replace not exists object")
  1372  	}
  1373  
  1374  	err := obj.insertReplace(ctx, octopus.InsertModeReplace)
  1375  
  1376  	if err == nil {
  1377  		metricStatCnt.Inc(ctx, "replace_success", 1)
  1378  	}
  1379  
  1380  	return err
  1381  }
  1382  
  1383  func (obj *{{ $PublicStructName }}) InsertOrReplace(ctx context.Context) error {
  1384  	metricStatCnt := activerecord.Metric().StatCount("octopus", "{{ $PublicStructName }}")
  1385  
  1386  	metricStatCnt.Inc(ctx, "insertorreplace_request", 1)
  1387  
  1388  	err := obj.insertReplace(ctx, octopus.InsertModeInserOrReplace)
  1389  
  1390  	if err == nil {
  1391  		metricStatCnt.Inc(ctx, "insertorreplace_success", 1)
  1392  	}
  1393  
  1394  	return err
  1395  }
  1396  
  1397  func (obj *{{ $PublicStructName }}) insertReplace(ctx context.Context, insertMode octopus.InsertMode) error {
  1398  	var (
  1399  		err error
  1400  		tuple [][]byte
  1401  		data []byte
  1402  	)
  1403  
  1404  	metricTimer := activerecord.Metric().Timer("octopus", "{{ $PublicStructName }}")
  1405  	metricErrCnt := activerecord.Metric().ErrorCount("octopus", "{{ $PublicStructName }}")
  1406  
  1407  	{{ range $ind, $fstruct := .FieldList }}
  1408  
  1409  	data, err = pack{{ $fstruct.Name }}([]byte{}, obj.Get{{ $fstruct.Name }}())
  1410  	if err != nil {
  1411  		metricErrCnt.Inc(ctx, "insertreplace_packfield", 1)
  1412  		return err
  1413  	}
  1414  
  1415  	tuple = append(tuple, data)
  1416  	{{ end }}
  1417  
  1418  	metricTimer.Timing(ctx, "insertreplace_packtuple")
  1419  
  1420  	if len(obj.BaseField.ExtraFields) > 0 {
  1421  		tuple = append(tuple, obj.BaseField.ExtraFields...)
  1422  	}
  1423  
  1424  	w := octopus.PackInsertReplace(namespace, insertMode, tuple)
  1425  	logger := activerecord.Logger()
  1426  
  1427  	metricTimer.Timing(ctx, "insertreplace_pack")
  1428  	logger.Trace(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Insert packed tuple: '%X'", w))
  1429  
  1430  	connection, err := octopus.Box(ctx, 0, activerecord.MasterInstanceType, "arcfg", nil)
  1431  	if err != nil {
  1432  		metricErrCnt.Inc(ctx, "insertreplace_preparebox", 1)
  1433  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Error get box '%s'", err))
  1434  
  1435  		return err
  1436  	}
  1437  
  1438  	respBytes, errCall := connection.Call(ctx, octopus.RequestTypeInsert, w)
  1439  	if errCall != nil {
  1440  		metricErrCnt.Inc(ctx, "insertreplace_box", 1)
  1441  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error insert into box", errCall, connection.Info())
  1442  
  1443  		return errCall
  1444  	}
  1445  
  1446  	metricTimer.Timing(ctx, "insertreplace_box")
  1447  
  1448  	logger.Trace(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), fmt.Sprintf("Response from box '%X'", respBytes))
  1449  
  1450  	tuplesData, err := octopus.ProcessResp(respBytes, octopus.NeedRespFlag|octopus.UniqRespFlag)
  1451  	if err != nil {
  1452  		metricErrCnt.Inc(ctx, "insertreplace_prespreparebox", 1)
  1453  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error parse response: ", err)
  1454  
  1455  		return err
  1456  	}
  1457  
  1458  	_, err = NewFromBox(ctx, tuplesData)
  1459  	if err != nil {
  1460  		metricErrCnt.Inc(ctx, "insertreplace_obj", 1)
  1461  		logger.Error(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Error in response: ", err)
  1462  
  1463  		return err
  1464  	}
  1465  
  1466  	obj.BaseField.Exists = true
  1467  	obj.BaseField.UpdateOps = []octopus.Ops{}
  1468  	{{- if gt $mutatorLen 0 }}
  1469  	obj.ClearMutatorUpdateOpts()
  1470  	{{- end }}
  1471  	obj.BaseField.Repaired = false
  1472  
  1473  	logger.Debug(ctx, "{{ $PublicStructName }}", obj.PrimaryString(), "Success insert")
  1474  
  1475  	metricTimer.Finish(ctx, "insertreplace")
  1476  
  1477  	return nil
  1478  }
  1479  {{ end }}
  1480  {{if gt $mutatorLen 0}}
  1481  func (obj *{{ $PublicStructName }}) ClearMutatorUpdateOpts() {
  1482  {{- range $ind, $fstruct := .FieldList -}}
  1483  	{{- range $i, $mut := $fstruct.Mutators -}}
  1484  		{{ $customMutator := index $mutators $mut -}}
  1485  		{{ if and (ne $customMutator.Update "") $customMutator.Name -}}
  1486  	obj.{{$customMutator.Name}}.UpdateOps = []octopus.Ops{}
  1487  	obj.{{$customMutator.Name}}.PartialFields = map[string]any{}
  1488  		{{- end }}
  1489  	{{end}}
  1490  {{- end -}}
  1491  }
  1492  {{end}}