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 = ×tampRange 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 }