github.com/optim-corp/cios-golang-sdk@v0.5.1/sdk/service/pubsub/datastore.go (about)

     1  package srvpubsub
     2  
     3  import (
     4  	"errors"
     5  	"log"
     6  	_nethttp "net/http"
     7  	"net/url"
     8  	"strconv"
     9  	"strings"
    10  	"time"
    11  
    12  	ciosutil "github.com/optim-corp/cios-golang-sdk/util/cios"
    13  
    14  	"github.com/optim-corp/cios-golang-sdk/cios"
    15  	ciosctx "github.com/optim-corp/cios-golang-sdk/ctx"
    16  	sdkmodel "github.com/optim-corp/cios-golang-sdk/model"
    17  	"github.com/optim-corp/cios-golang-sdk/util"
    18  
    19  	"github.com/fcfcqloow/go-advance/check"
    20  	cnv "github.com/fcfcqloow/go-advance/convert"
    21  	xmath "github.com/fcfcqloow/go-advance/math"
    22  
    23  	"github.com/gorilla/websocket"
    24  )
    25  
    26  func MakeGetDataStoreChannelsOpts() cios.ApiGetDataStoreChannelsRequest {
    27  	return cios.ApiGetDataStoreChannelsRequest{}
    28  }
    29  
    30  func MakeGetObjectsOpts() cios.ApiGetDataStoreObjectsRequest {
    31  	return cios.ApiGetDataStoreObjectsRequest{}
    32  }
    33  func MakeGetStreamOpts() sdkmodel.ApiGetStreamRequest {
    34  	return sdkmodel.ApiGetStreamRequest{}
    35  }
    36  func (self *CiosPubSub) GetDataStoreChannels(ctx ciosctx.RequestCtx, params cios.ApiGetDataStoreChannelsRequest) (response cios.MultipleDataStoreChannel, httpResponse *_nethttp.Response, err error) {
    37  	if err = self.refresh(); err != nil {
    38  		return
    39  	}
    40  	params.Ctx = self.withHost(ctx)
    41  	params.ApiService = self.ApiClient.PublishSubscribeApi
    42  	params.P_order = util.ToNil(params.P_order)
    43  	params.P_orderBy = util.ToNil(params.P_orderBy)
    44  	params.P_channelProtocolId = util.ToNil(params.P_channelProtocolId)
    45  	return params.Execute()
    46  }
    47  func (self *CiosPubSub) GetDataStoreChannel(ctx ciosctx.RequestCtx, channelID string) (cios.DataStoreChannel, *_nethttp.Response, error) {
    48  	if err := self.refresh(); err != nil {
    49  		return cios.DataStoreChannel{}, nil, err
    50  	}
    51  	request := self.ApiClient.PublishSubscribeApi.GetDataStoreChannel(self.withHost(ctx), channelID)
    52  	response, httpResponse, err := request.Execute()
    53  	if err != nil {
    54  		return cios.DataStoreChannel{}, httpResponse, err
    55  	}
    56  
    57  	return response.Channel, httpResponse, err
    58  }
    59  func (self *CiosPubSub) GetObjects(ctx ciosctx.RequestCtx, channelID string, params cios.ApiGetDataStoreObjectsRequest) (response cios.MultipleDataStoreObject, httpResponse *_nethttp.Response, err error) {
    60  	if err = self.refresh(); err != nil {
    61  		return
    62  	}
    63  	params.ApiService = self.ApiClient.PublishSubscribeApi
    64  	params.Ctx = self.withHost(ctx)
    65  	params.P_channelId = channelID
    66  	params.P_label = util.ToNil(params.P_label)
    67  	params.P_location = util.ToNil(params.P_location)
    68  	params.P_locationRange = util.ToNil(params.P_locationRange)
    69  	params.P_sessionId = util.ToNil(params.P_sessionId)
    70  	params.P_timestamp = util.ToNil(params.P_timestamp)
    71  	params.P_timestampRange = util.ToNil(params.P_timestampRange)
    72  	params.P_channelProtocolId = util.ToNil(params.P_channelProtocolId)
    73  	return params.Execute()
    74  }
    75  func (self *CiosPubSub) GetObjectsAll(ctx ciosctx.RequestCtx, channelID string, params cios.ApiGetDataStoreObjectsRequest) ([]cios.DataStoreObject, *_nethttp.Response, error) {
    76  	var (
    77  		result      []cios.DataStoreObject
    78  		httpRes     *_nethttp.Response
    79  		err         error
    80  		offset      = int64(0)
    81  		_limit      = int64(1000)
    82  		getFunction = func(offset int64) (cios.MultipleDataStoreObject, *_nethttp.Response, error) {
    83  			return self.GetObjects(ctx, channelID, params.Limit(xmath.MinInt64(_limit, 1000)).Offset(offset+cnv.MustInt64(params.P_offset)))
    84  		}
    85  	)
    86  	if params.P_limit != nil {
    87  		_limit = *params.P_limit
    88  		for {
    89  			res, httpRes, err := getFunction(offset)
    90  			if err != nil {
    91  				return nil, httpRes, err
    92  			}
    93  			result = append(result, res.Objects...)
    94  			offset += 1000
    95  			_limit -= 1000
    96  			if _limit <= 0 {
    97  				break
    98  			}
    99  		}
   100  	} else {
   101  		res, httpRes, err := getFunction(offset)
   102  		if err != nil {
   103  			return nil, httpRes, err
   104  		}
   105  		result = append(result, res.Objects...)
   106  		for offset = int64(1000); offset+cnv.MustInt64(params.P_offset) < res.Total; offset += 1000 {
   107  			res, httpRes, err = getFunction(offset)
   108  			if err != nil {
   109  				return nil, httpRes, err
   110  			}
   111  			result = append(result, res.Objects...)
   112  		}
   113  	}
   114  	return result, httpRes, err
   115  }
   116  func (self *CiosPubSub) GetObjectsUnlimited(ctx ciosctx.RequestCtx, channelID string, params cios.ApiGetDataStoreObjectsRequest) ([]cios.DataStoreObject, *_nethttp.Response, error) {
   117  	params.P_limit = nil
   118  	return self.GetObjectsAll(ctx, channelID, params)
   119  }
   120  func (self *CiosPubSub) GetObject(ctx ciosctx.RequestCtx, channelID string, objectID string, packerFormat *string) (interface{}, *_nethttp.Response, error) {
   121  	if err := self.refresh(); err != nil {
   122  		return map[string]interface{}{}, nil, err
   123  	}
   124  	request := self.ApiClient.PublishSubscribeApi.GetDataStoreObjectData(self.withHost(ctx), channelID, objectID)
   125  	if packerFormat != nil {
   126  		request = request.PackerFormat(*packerFormat)
   127  	}
   128  	return request.Execute()
   129  }
   130  func (self *CiosPubSub) GetObjectLatest(ctx ciosctx.RequestCtx, channelID string, packerFormat *string) (interface{}, *_nethttp.Response, error) {
   131  	if err := self.refresh(); err != nil {
   132  		return map[string]interface{}{}, nil, err
   133  	}
   134  	request := self.ApiClient.PublishSubscribeApi.GetDataStoreObjectDataLatest(self.withHost(ctx), channelID)
   135  	if packerFormat != nil {
   136  		request = request.PackerFormat(*packerFormat)
   137  	}
   138  	return request.Execute()
   139  
   140  }
   141  func (self *CiosPubSub) MapObjectLatest(ctx ciosctx.RequestCtx, channelID string, packerFormat *string, stc interface{}) (*_nethttp.Response, error) {
   142  	if err := self.refresh(); err != nil {
   143  		return nil, err
   144  	}
   145  	response, httpResponse, err := self.GetObjectLatest(ctx, channelID, packerFormat)
   146  	if err != nil {
   147  		return httpResponse, err
   148  	}
   149  	return httpResponse, cnv.DeepCopy(response, stc)
   150  }
   151  func (self *CiosPubSub) GetMultiObjectLatest(ctx ciosctx.RequestCtx, channelIDs []string) (cios.MultipleDataStoreDataLatest, *_nethttp.Response, error) {
   152  	if err := self.refresh(); err != nil {
   153  		return cios.MultipleDataStoreDataLatest{}, nil, err
   154  	}
   155  	request := self.ApiClient.PublishSubscribeApi.GetDataStoreMultiObjectDataLatest(self.withHost(ctx)).Ids(cios.Ids{Ids: &channelIDs})
   156  	return request.Execute()
   157  }
   158  func (self *CiosPubSub) GetMultiObjectLatestByChannels(ctx ciosctx.RequestCtx, channels []cios.Channel) (cios.MultipleDataStoreDataLatest, *_nethttp.Response, error) {
   159  	var channelIDs []string
   160  	for _, channel := range channels {
   161  		channelIDs = append(channelIDs, channel.Id)
   162  	}
   163  	return self.GetMultiObjectLatest(ctx, channelIDs)
   164  }
   165  func (self *CiosPubSub) MapMultiObjectLatestPayload(ctx ciosctx.RequestCtx, channelIDs []string, stc interface{}) ([]cios.PackerFormatJsonHeader, *_nethttp.Response, error) {
   166  	var headers []cios.PackerFormatJsonHeader
   167  	objects, httpResponse, err := self.GetMultiObjectLatest(ctx, channelIDs)
   168  	if err == nil {
   169  		headers, err = ciosutil.MapPayloads(*objects.Objects, stc)
   170  	}
   171  	return headers, httpResponse, err
   172  }
   173  func (self *CiosPubSub) MapMultiObjectLatestPayloadByChannels(ctx ciosctx.RequestCtx, channels []cios.Channel, stc interface{}) ([]cios.PackerFormatJsonHeader, *_nethttp.Response, error) {
   174  	var channelIDs []string
   175  	for _, channel := range channels {
   176  		channelIDs = append(channelIDs, channel.Id)
   177  	}
   178  	return self.MapMultiObjectLatestPayload(ctx, channelIDs, stc)
   179  }
   180  func (self *CiosPubSub) subscribeCiosWebSocket(ctx ciosctx.RequestCtx, _url string, beforeFunc *func(*websocket.Conn), logic func(body []byte) (bool, error), wsR, wsW int64) error {
   181  	if ctx != nil {
   182  		if _token, ok := ctx.Value(cios.ContextAccessToken).(string); ok {
   183  			self.token = &_token
   184  		}
   185  	}
   186  	if cnv.MustStr(self.token) == "" {
   187  		if err := self.refresh(); err != nil {
   188  			return err
   189  		}
   190  	}
   191  	connection, err := self.CreateCIOSWebsocketConnection(_url, ciosutil.ParseAccessToken(cnv.MustStr(self.token)))
   192  	if err != nil {
   193  		return err
   194  	}
   195  	defer connection.Close()
   196  	if beforeFunc != nil {
   197  		(*beforeFunc)(connection)
   198  	}
   199  	for {
   200  		if wsR != 0 {
   201  			if err := connection.SetReadDeadline(time.Now().Add(time.Millisecond * time.Duration(wsR))); err != nil {
   202  				return err
   203  			}
   204  		}
   205  		if connection == nil {
   206  			return errors.New("failed websocket connection")
   207  		}
   208  		messageType, body, err := connection.ReadMessage()
   209  		switch {
   210  		case websocket.IsCloseError(err, websocket.CloseNormalClosure):
   211  			return nil
   212  		case websocket.IsUnexpectedCloseError(err):
   213  			if _err := self.refresh(); _err != nil {
   214  				return _err
   215  			}
   216  			connection.Close()
   217  			if connection, err = self.CreateCIOSWebsocketConnection(_url, ciosutil.ParseAccessToken(cnv.MustStr(self.token))); err != nil {
   218  				return err
   219  			}
   220  		case messageType == websocket.CloseMessage:
   221  			return errors.New(string(body))
   222  		case messageType == websocket.TextMessage:
   223  			if done, err := logic(body); err != nil || done {
   224  				return err
   225  			}
   226  		}
   227  	}
   228  }
   229  
   230  func (self *CiosPubSub) GetStream(ctx ciosctx.RequestCtx, channelID string, params sdkmodel.ApiGetStreamRequest) ([]string, error) {
   231  	var (
   232  		result                    []string
   233  		channelProtocolVersionStr *string
   234  		ascendingStr              = "false"
   235  		offsetStr                 = "0"
   236  		limitStr                  *string
   237  		_url, _                   = url.Parse(strings.Replace(self.Url, "https", "wss", 1) + "/v2/datastore/channels/" + channelID + "/object_stream")
   238  	)
   239  	if params.AscendingParam != nil {
   240  		ascendingStr = strconv.FormatBool(*params.AscendingParam)
   241  	}
   242  	if params.OffsetParam != nil {
   243  		offsetStr = strconv.FormatInt(*params.OffsetParam, 10)
   244  	}
   245  	if params.ChannelProtocolVersionParam != nil {
   246  		tmp := strconv.FormatInt(int64(*params.ChannelProtocolVersionParam), 10)
   247  		channelProtocolVersionStr = &tmp
   248  	}
   249  	if params.LimitParam != nil {
   250  		limitStr = cnv.StrPtr(cnv.MustStr(params.LimitParam))
   251  	}
   252  	_url.RawQuery = util.Query(_url, util.QueryMap{
   253  		"packer_format":            params.PackerFormatParam,
   254  		"ascending":                &ascendingStr,
   255  		"channel_protocol_id":      params.ChannelProtocolIdParam,
   256  		"channel_protocol_version": channelProtocolVersionStr,
   257  		"session_id":               params.SessionIdParam,
   258  		"location":                 params.LocationParam,
   259  		"location_range":           params.LocationRangeParam,
   260  		"timestamp":                params.TimestampParam,
   261  		"timestamp_range":          params.TimestampRangeParam,
   262  		"label":                    params.LabelParam,
   263  		"offset":                   &offsetStr,
   264  		"limit":                    limitStr,
   265  	})
   266  	bf := func(conn *websocket.Conn) {
   267  		if err := conn.WriteMessage(websocket.TextMessage, []byte("load")); err != nil {
   268  			panic(err)
   269  		}
   270  		if params.TimeoutParam != nil {
   271  			if err := conn.SetReadDeadline(time.Now().Add(time.Duration(*params.TimeoutParam) * time.Second)); err != nil {
   272  				panic(err)
   273  			}
   274  		}
   275  	}
   276  	err := self.subscribeCiosWebSocket(ctx, _url.String(), &bf,
   277  		func(body []byte) (bool, error) {
   278  			result = append(result, string(body))
   279  			return false, nil
   280  		}, self.wsReadTimeout, self.wsWriteTimeout,
   281  	)
   282  	if self.debug {
   283  		log.Println(result)
   284  	}
   285  	return result, err
   286  }
   287  func (self *CiosPubSub) GetStreamAll(ctx ciosctx.RequestCtx, channelID string, params sdkmodel.ApiGetStreamRequest) ([]string, error) {
   288  	var (
   289  		result      []string
   290  		err         error
   291  		offset      = int64(0)
   292  		_limit      = int64(1000)
   293  		getFunction = func(offset int64) ([]string, error) {
   294  			return self.GetStream(ctx, channelID, params.Limit(xmath.MinInt64(_limit, 1000)).Offset(offset+cnv.MustInt64(params.OffsetParam)))
   295  		}
   296  	)
   297  	if params.LimitParam != nil {
   298  		_limit = *params.LimitParam
   299  		for {
   300  			res, err := getFunction(offset)
   301  			if err != nil {
   302  				return nil, err
   303  			}
   304  			result = append(result, res...)
   305  			offset += 1000
   306  			_limit -= 1000
   307  			if _limit <= 0 {
   308  				break
   309  			}
   310  		}
   311  	} else {
   312  		for {
   313  			res, err := getFunction(offset)
   314  			if err != nil {
   315  				break
   316  			}
   317  
   318  			result = append(result, res...)
   319  			if len(res) < 1000 {
   320  				break
   321  			}
   322  			offset += 1000
   323  		}
   324  	}
   325  	return result, err
   326  }
   327  func (self *CiosPubSub) GetStreamUnlimited(ctx ciosctx.RequestCtx, channelID string, params sdkmodel.ApiGetStreamRequest) ([]string, error) {
   328  	if params.TimestampRangeParam == nil {
   329  		timestampRange := ":" + cnv.MustStr(time.Now().UnixNano())
   330  		params.TimestampRangeParam = &timestampRange
   331  	}
   332  	params.LimitParam = nil
   333  	return self.GetStreamAll(ctx, channelID, params)
   334  }
   335  func (self *CiosPubSub) MapStreamAll(ctx ciosctx.RequestCtx, channelID string, params sdkmodel.ApiGetStreamRequest, stc interface{}) error {
   336  	data, err := self.GetStreamAll(ctx, channelID, params)
   337  	if err != nil {
   338  		return err
   339  	}
   340  	return ciosutil.DataStoreStreamToStruct(data, stc)
   341  }
   342  func (self *CiosPubSub) MapStreamUnlimited(ctx ciosctx.RequestCtx, channelID string, params sdkmodel.ApiGetStreamRequest, stc interface{}) error {
   343  	data, err := self.GetStreamUnlimited(ctx, channelID, params)
   344  	if err != nil {
   345  		return err
   346  	}
   347  	return ciosutil.DataStoreStreamToStruct(data, stc)
   348  }
   349  func (self *CiosPubSub) GetJsonStreamUnlimited(ctx ciosctx.RequestCtx, channelID string, params sdkmodel.ApiGetStreamRequest) (result []cios.PackerFormatJson, err error) {
   350  	params.PackerFormatParam = cnv.StrPtr("json")
   351  	data, _err := self.GetStreamUnlimited(ctx, channelID, params)
   352  	if _err != nil {
   353  		err = _err
   354  	}
   355  	err = ciosutil.DataStoreStreamToStruct(data, &result)
   356  	return
   357  }
   358  func (self *CiosPubSub) GetStreamFirst(ctx ciosctx.RequestCtx, channelID string, params sdkmodel.ApiGetStreamRequest) (string, error) {
   359  	value, err := self.GetStreamAll(ctx, channelID, params.Limit(1))
   360  	if err != nil {
   361  		if value, err = self.GetStreamAll(ctx, channelID, params.Limit(1)); err != nil {
   362  			return "", err
   363  		}
   364  	}
   365  	if len(value) == 0 {
   366  		return "", nil
   367  	}
   368  	return value[0], err
   369  }
   370  func (self *CiosPubSub) MapStreamFirst(ctx ciosctx.RequestCtx, channelID string, params sdkmodel.ApiGetStreamRequest, stc interface{}) error {
   371  	value, err := self.GetStreamFirst(ctx, channelID, params)
   372  	if err != nil {
   373  		return err
   374  	}
   375  	return cnv.UnMarshalJson([]byte(value), stc)
   376  }
   377  func (self *CiosPubSub) DeleteDataByChannel(ctx ciosctx.RequestCtx, channelID string) (*_nethttp.Response, error) {
   378  	if err := self.refresh(); err != nil {
   379  		return nil, err
   380  	}
   381  	request := self.ApiClient.PublishSubscribeApi.DeleteDataStoreChannel(self.withHost(ctx), channelID)
   382  	httpResponse, err := request.Execute()
   383  	if err != nil && !check.IsNil(self.refresh) {
   384  		httpResponse, err = request.Execute()
   385  	}
   386  	return httpResponse, err
   387  }
   388  func (self *CiosPubSub) DeleteObject(ctx ciosctx.RequestCtx, channelID string, objectID string) (*_nethttp.Response, error) {
   389  	if err := self.refresh(); err != nil {
   390  		return nil, err
   391  	}
   392  	request := self.ApiClient.PublishSubscribeApi.DeleteDataStoreObjectData(self.withHost(ctx), channelID, objectID)
   393  	_, hErr, err := request.Execute()
   394  	if err != nil && !check.IsNil(self.refresh) {
   395  		_, hErr, err = request.Execute()
   396  	}
   397  	return hErr, err
   398  }