github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/modules/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  
     7  	confid "github.com/machinefi/w3bstream/pkg/depends/conf/id"
     8  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx"
     9  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/builder"
    10  	"github.com/machinefi/w3bstream/pkg/depends/kit/statusx"
    11  	"github.com/machinefi/w3bstream/pkg/enums"
    12  	"github.com/machinefi/w3bstream/pkg/errors/status"
    13  	"github.com/machinefi/w3bstream/pkg/models"
    14  	"github.com/machinefi/w3bstream/pkg/types"
    15  	"github.com/machinefi/w3bstream/pkg/types/wasm"
    16  )
    17  
    18  func Marshal(c wasm.Configuration) (data []byte, err error) {
    19  	data, err = json.Marshal(c)
    20  	if err != nil {
    21  		err = status.ConfigParseFailed.StatusErr().WithDesc(err.Error())
    22  	}
    23  	return
    24  }
    25  
    26  func Unmarshal(data []byte, typ enums.ConfigType) (c wasm.Configuration, err error) {
    27  	c, err = wasm.NewUserConfigurationByType(typ)
    28  	if err != nil {
    29  		return nil, status.InvalidConfigType.StatusErr().WithDesc(err.Error())
    30  	}
    31  	if err = json.Unmarshal(data, c); err != nil {
    32  		return nil, status.ConfigParseFailed.StatusErr().WithDesc(err.Error())
    33  	}
    34  	return c, nil
    35  }
    36  
    37  func GetBySFID(ctx context.Context, id types.SFID) (*models.Config, error) {
    38  	d := types.MustMgrDBExecutorFromContext(ctx)
    39  	m := &models.Config{RelConfig: models.RelConfig{ConfigID: id}}
    40  
    41  	if err := m.FetchByConfigID(d); err != nil {
    42  		if sqlx.DBErr(err).IsNotFound() {
    43  			return nil, status.ConfigNotFound
    44  		}
    45  		return nil, status.DatabaseError.StatusErr().WithDesc(err.Error())
    46  	}
    47  	return m, nil
    48  }
    49  
    50  func GetValueBySFID(ctx context.Context, id types.SFID) (wasm.Configuration, error) {
    51  	m, err := GetBySFID(ctx, id)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	return Unmarshal(m.Value, m.Type)
    56  }
    57  
    58  func GetByRelAndType(ctx context.Context, id types.SFID, t enums.ConfigType) (*models.Config, error) {
    59  	d := types.MustMgrDBExecutorFromContext(ctx)
    60  	m := &models.Config{ConfigBase: models.ConfigBase{RelID: id, Type: t}}
    61  	v := &Detail{id, t}
    62  
    63  	if err := m.FetchByRelIDAndType(d); err != nil {
    64  		if sqlx.DBErr(err).IsNotFound() {
    65  			return nil, status.ConfigNotFound.StatusErr().WithDesc(v.Log(err))
    66  		}
    67  		return nil, status.DatabaseError.StatusErr().WithDesc(v.Log(err))
    68  	}
    69  	return m, nil
    70  }
    71  
    72  func GetValueByRelAndType(ctx context.Context, rel types.SFID, t enums.ConfigType) (wasm.Configuration, error) {
    73  	m, err := GetByRelAndType(ctx, rel, t)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	return Unmarshal(m.Value, t)
    78  }
    79  
    80  func Upsert(ctx context.Context, rel types.SFID, c wasm.Configuration) (*models.Config, error) {
    81  	var (
    82  		d   = types.MustMgrDBExecutorFromContext(ctx)
    83  		idg = confid.MustSFIDGeneratorFromContext(ctx)
    84  		v   = &Detail{rel, c}
    85  		err error
    86  		m   *models.Config
    87  		old wasm.Configuration
    88  	)
    89  
    90  	err = sqlx.NewTasks(d).With(
    91  		func(d sqlx.DBExecutor) error {
    92  			m = &models.Config{
    93  				ConfigBase: models.ConfigBase{RelID: rel, Type: c.ConfigType()},
    94  			}
    95  			if err = m.FetchByRelIDAndType(d); err != nil {
    96  				if sqlx.DBErr(err).IsNotFound() {
    97  					return nil
    98  				}
    99  				return status.DatabaseError.StatusErr().WithDesc(v.Log(err))
   100  			}
   101  			if old, err = Unmarshal(m.Value, c.ConfigType()); err != nil {
   102  				return err
   103  			}
   104  			if err = wasm.UninitConfiguration(ctx, old); err != nil {
   105  				return status.ConfigUninitFailed.StatusErr().WithDesc(v.Log(err))
   106  			}
   107  			return nil
   108  		},
   109  		func(d sqlx.DBExecutor) error {
   110  			var raw []byte
   111  			raw, err = Marshal(c)
   112  			if err != nil {
   113  				return err
   114  			}
   115  			if old == nil {
   116  				m = &models.Config{
   117  					RelConfig: models.RelConfig{ConfigID: idg.MustGenSFID()},
   118  					ConfigBase: models.ConfigBase{
   119  						Type: c.ConfigType(), RelID: rel, Value: raw,
   120  					},
   121  				}
   122  				err = m.Create(d)
   123  			} else {
   124  				m.Value = raw
   125  				err = m.UpdateByRelIDAndType(d)
   126  			}
   127  			if err != nil {
   128  				if sqlx.DBErr(err).IsConflict() {
   129  					return status.ConfigConflict.StatusErr().WithDesc(v.Log(err))
   130  				}
   131  				return status.DatabaseError.StatusErr().WithDesc(err.Error())
   132  			}
   133  			return nil
   134  		},
   135  		func(d sqlx.DBExecutor) error {
   136  			if err = wasm.InitConfiguration(ctx, c); err != nil {
   137  				return status.ConfigInitFailed.StatusErr().WithDesc(v.Log(err))
   138  			}
   139  			return nil
   140  		},
   141  	).Do()
   142  
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	return m, nil
   147  }
   148  
   149  func List(ctx context.Context, r *CondArgs) ([]*Detail, error) {
   150  	var (
   151  		d = types.MustMgrDBExecutorFromContext(ctx)
   152  		m = &models.Config{}
   153  		c wasm.Configuration
   154  	)
   155  
   156  	lst, err := m.List(d, r.Condition())
   157  	if err != nil {
   158  		return nil, status.DatabaseError.StatusErr().WithDesc(err.Error())
   159  	}
   160  
   161  	configs := make([]*Detail, 0, len(lst))
   162  	for _, cfg := range lst {
   163  		c, err = Unmarshal(cfg.Value, cfg.Type)
   164  		if err != nil {
   165  			return nil, err
   166  		}
   167  		configs = append(configs, &Detail{RelID: cfg.RelID, Configuration: c})
   168  	}
   169  	return configs, nil
   170  }
   171  
   172  func Remove(ctx context.Context, r *CondArgs) error {
   173  	var (
   174  		d   = types.MustMgrDBExecutorFromContext(ctx)
   175  		m   = &models.Config{}
   176  		lst []*Detail
   177  		err error
   178  	)
   179  
   180  	return sqlx.NewTasks(d).With(
   181  		func(d sqlx.DBExecutor) error {
   182  			ctx := types.WithMgrDBExecutor(ctx, d)
   183  			lst, err = List(ctx, r)
   184  			return err
   185  		},
   186  		func(d sqlx.DBExecutor) error {
   187  			if _, err = d.Exec(
   188  				builder.Delete().From(d.T(m), builder.Where(r.Condition())),
   189  			); err != nil {
   190  				return status.DatabaseError.StatusErr().WithDesc(err.Error())
   191  			}
   192  			return nil
   193  		},
   194  		func(db sqlx.DBExecutor) error {
   195  			summary := make(statusx.ErrorFields, 0, len(lst))
   196  			for _, c := range lst {
   197  				err2 := wasm.UninitConfiguration(ctx, c.Configuration)
   198  				if err2 != nil {
   199  					summary = append(summary, &statusx.ErrorField{
   200  						Field: c.String(), Msg: err2.Error(),
   201  					})
   202  				}
   203  			}
   204  			if len(summary) > 0 {
   205  				return status.ConfigUninitFailed.StatusErr().
   206  					AppendErrorFields(summary...)
   207  			}
   208  			return nil
   209  		},
   210  	).Do()
   211  }
   212  
   213  func Create(ctx context.Context, id types.SFID, c wasm.Configuration) (*models.Config, error) {
   214  	var (
   215  		d = types.MustMgrDBExecutorFromContext(ctx)
   216  		v = &Detail{id, c}
   217  	)
   218  
   219  	raw, err := Marshal(c)
   220  	if err != nil {
   221  		return nil, err
   222  	}
   223  
   224  	m := &models.Config{
   225  		RelConfig: models.RelConfig{
   226  			ConfigID: confid.MustSFIDGeneratorFromContext(ctx).MustGenSFID(),
   227  		},
   228  		ConfigBase: models.ConfigBase{
   229  			RelID: id, Type: c.ConfigType(), Value: raw,
   230  		},
   231  	}
   232  
   233  	err = sqlx.NewTasks(d).With(
   234  		func(db sqlx.DBExecutor) error {
   235  			if err = m.Create(d); err != nil {
   236  				if sqlx.DBErr(err).IsConflict() {
   237  					return status.ConfigConflict.StatusErr().WithDesc(v.Log(err))
   238  				}
   239  				return status.DatabaseError.StatusErr().WithDesc(err.Error())
   240  			}
   241  			return nil
   242  		},
   243  		func(db sqlx.DBExecutor) error {
   244  			if err = wasm.InitConfiguration(ctx, c); err != nil {
   245  				return status.ConfigInitFailed.StatusErr().
   246  					WithDesc(v.Log(err))
   247  			}
   248  			return nil
   249  		},
   250  	).Do()
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  	return m, nil
   255  }