github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/core/service/session.go (about) 1 /* 2 * Copyright (C) 2020 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package service 19 20 import ( 21 "sync" 22 "time" 23 24 "github.com/ethereum/go-ethereum/common" 25 "github.com/gofrs/uuid" 26 "github.com/rs/zerolog/log" 27 28 "github.com/mysteriumnetwork/node/identity" 29 "github.com/mysteriumnetwork/node/market" 30 "github.com/mysteriumnetwork/node/pb" 31 "github.com/mysteriumnetwork/node/session" 32 "github.com/mysteriumnetwork/node/session/event" 33 "github.com/mysteriumnetwork/node/trace" 34 ) 35 36 // Session structure holds all required information about current session between service consumer and provider. 37 type Session struct { 38 ID session.ID 39 ConsumerID identity.Identity 40 ConsumerLocation market.Location 41 HermesID common.Address 42 Proposal market.ServiceProposal 43 ServiceID string 44 CreatedAt time.Time 45 request *pb.SessionRequest 46 done chan struct{} 47 cleanupLock sync.Mutex 48 cleanup []func() error 49 tracer *trace.Tracer 50 once sync.Once 51 } 52 53 // Close ends session. 54 func (s *Session) Close() { 55 s.once.Do(func() { 56 close(s.done) 57 58 s.cleanupLock.Lock() 59 defer s.cleanupLock.Unlock() 60 61 for i := len(s.cleanup) - 1; i >= 0; i-- { 62 log.Trace().Msgf("Session cleaning up: (%v/%v)", i+1, len(s.cleanup)) 63 err := s.cleanup[i]() 64 if err != nil { 65 log.Warn().Err(err).Msg("Cleanup error") 66 } 67 } 68 s.cleanup = nil 69 }) 70 } 71 72 // Done returns readonly done channel. 73 func (s *Session) Done() <-chan struct{} { 74 return s.done 75 } 76 77 func (s *Session) addCleanup(fn func() error) { 78 s.cleanupLock.Lock() 79 defer s.cleanupLock.Unlock() 80 81 // If add cleanup is called after the session close, clean up immediately. 82 // Otherwise, add it to be cleaned up later. 83 select { 84 case <-s.done: 85 err := fn() 86 if err != nil { 87 log.Warn().Err(err).Msg("Cleanup error") 88 } 89 default: 90 s.cleanup = append(s.cleanup, fn) 91 } 92 } 93 94 func (s *Session) toEvent(status event.Status) event.AppEventSession { 95 return event.AppEventSession{ 96 Status: status, 97 Service: event.ServiceContext{ 98 ID: s.ServiceID, 99 }, 100 Session: event.SessionContext{ 101 ID: string(s.ID), 102 StartedAt: s.CreatedAt, 103 ConsumerID: s.ConsumerID, 104 ConsumerLocation: s.ConsumerLocation, 105 HermesID: s.HermesID, 106 Proposal: s.Proposal, 107 }, 108 } 109 } 110 111 // NewSession creates a blank new session with an ID. 112 func NewSession(service *Instance, request *pb.SessionRequest, tracer *trace.Tracer) (*Session, error) { 113 uid, err := uuid.NewV4() 114 if err != nil { 115 return nil, err 116 } 117 118 var consumerLocation market.Location 119 if location := request.GetConsumer().GetLocation(); location != nil { 120 consumerLocation.Country = location.GetCountry() 121 } 122 123 return &Session{ 124 ID: session.ID(uid.String()), 125 ConsumerID: identity.FromAddress(request.GetConsumer().GetId()), 126 ConsumerLocation: consumerLocation, 127 HermesID: common.HexToAddress(request.GetConsumer().GetHermesID()), 128 Proposal: service.CopyProposal(), 129 ServiceID: string(service.ID), 130 CreatedAt: time.Now().UTC(), 131 request: request, 132 done: make(chan struct{}), 133 cleanup: make([]func() error, 0), 134 tracer: tracer, 135 }, nil 136 }