github.com/livekit/protocol@v1.16.1-0.20240517185851-47e4c6bba773/rpc/typed_api.go (about) 1 // Copyright 2023 LiveKit, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package rpc 16 17 import ( 18 "context" 19 "fmt" 20 "time" 21 22 "github.com/livekit/protocol/livekit" 23 "github.com/livekit/protocol/logger" 24 "github.com/livekit/protocol/utils/must" 25 "github.com/livekit/psrpc" 26 "github.com/livekit/psrpc/pkg/middleware" 27 ) 28 29 type PSRPCConfig struct { 30 MaxAttempts int `yaml:"max_attempts,omitempty"` 31 Timeout time.Duration `yaml:"timeout,omitempty"` 32 Backoff time.Duration `yaml:"backoff,omitempty"` 33 BufferSize int `yaml:"buffer_size,omitempty"` 34 } 35 36 var DefaultPSRPCConfig = PSRPCConfig{ 37 MaxAttempts: 3, 38 Timeout: 3 * time.Second, 39 Backoff: 2 * time.Second, 40 BufferSize: 1000, 41 } 42 43 type ClientParams struct { 44 PSRPCConfig 45 Bus psrpc.MessageBus 46 Logger logger.Logger 47 Observer middleware.MetricsObserver 48 } 49 50 func NewClientParams( 51 config PSRPCConfig, 52 bus psrpc.MessageBus, 53 logger logger.Logger, 54 observer middleware.MetricsObserver, 55 ) ClientParams { 56 return ClientParams{ 57 PSRPCConfig: config, 58 Bus: bus, 59 Logger: logger, 60 Observer: observer, 61 } 62 } 63 64 func (p *ClientParams) Options() []psrpc.ClientOption { 65 opts := make([]psrpc.ClientOption, 0, 4) 66 if p.BufferSize != 0 { 67 opts = append(opts, psrpc.WithClientChannelSize(p.BufferSize)) 68 } 69 if p.Observer != nil { 70 opts = append(opts, middleware.WithClientMetrics(p.Observer)) 71 } 72 if p.Logger != nil { 73 opts = append(opts, WithClientLogger(p.Logger)) 74 } 75 if p.MaxAttempts != 0 || p.Timeout != 0 || p.Backoff != 0 { 76 opts = append(opts, middleware.WithRPCRetries(middleware.RetryOptions{ 77 MaxAttempts: p.MaxAttempts, 78 Timeout: p.Timeout, 79 Backoff: p.Backoff, 80 })) 81 } 82 return opts 83 } 84 85 //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate 86 87 type TypedSignalClient = SignalClient[livekit.NodeID] 88 type TypedSignalServer = SignalServer[livekit.NodeID] 89 90 func NewTypedSignalClient(nodeID livekit.NodeID, bus psrpc.MessageBus, opts ...psrpc.ClientOption) (TypedSignalClient, error) { 91 return NewSignalClient[livekit.NodeID](bus, append(opts[:len(opts):len(opts)], psrpc.WithClientID(string(nodeID)))...) 92 } 93 94 func NewTypedSignalServer(nodeID livekit.NodeID, svc SignalServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOption) (TypedSignalServer, error) { 95 return NewSignalServer[livekit.NodeID](svc, bus, append(opts[:len(opts):len(opts)], psrpc.WithServerID(string(nodeID)))...) 96 } 97 98 type ParticipantTopic string 99 type RoomTopic string 100 101 func FormatParticipantTopic(roomName livekit.RoomName, identity livekit.ParticipantIdentity) ParticipantTopic { 102 return ParticipantTopic(fmt.Sprintf("%s_%s", roomName, identity)) 103 } 104 105 func FormatRoomTopic(roomName livekit.RoomName) RoomTopic { 106 return RoomTopic(roomName) 107 } 108 109 type topicFormatter struct{} 110 111 func NewTopicFormatter() TopicFormatter { 112 return topicFormatter{} 113 } 114 115 func (f topicFormatter) ParticipantTopic(ctx context.Context, roomName livekit.RoomName, identity livekit.ParticipantIdentity) ParticipantTopic { 116 return FormatParticipantTopic(roomName, identity) 117 } 118 119 func (f topicFormatter) RoomTopic(ctx context.Context, roomName livekit.RoomName) RoomTopic { 120 return FormatRoomTopic(roomName) 121 } 122 123 type TopicFormatter interface { 124 ParticipantTopic(ctx context.Context, roomName livekit.RoomName, identity livekit.ParticipantIdentity) ParticipantTopic 125 RoomTopic(ctx context.Context, roomName livekit.RoomName) RoomTopic 126 } 127 128 //counterfeiter:generate . TypedRoomClient 129 type TypedRoomClient = RoomClient[RoomTopic] 130 type TypedRoomServer = RoomServer[RoomTopic] 131 132 func NewTypedRoomClient(params ClientParams) (TypedRoomClient, error) { 133 return NewRoomClient[RoomTopic](params.Bus, params.Options()...) 134 } 135 136 func NewTypedRoomServer(svc RoomServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOption) (TypedRoomServer, error) { 137 return NewRoomServer[RoomTopic](svc, bus, opts...) 138 } 139 140 //counterfeiter:generate . TypedParticipantClient 141 type TypedParticipantClient = ParticipantClient[ParticipantTopic] 142 type TypedParticipantServer = ParticipantServer[ParticipantTopic] 143 144 func NewTypedParticipantClient(params ClientParams) (TypedParticipantClient, error) { 145 return NewParticipantClient[ParticipantTopic](params.Bus, params.Options()...) 146 } 147 148 func NewTypedParticipantServer(svc ParticipantServerImpl, bus psrpc.MessageBus, opts ...psrpc.ServerOption) (TypedParticipantServer, error) { 149 return NewParticipantServer[ParticipantTopic](svc, bus, opts...) 150 } 151 152 //counterfeiter:generate . KeepalivePubSub 153 type KeepalivePubSub interface { 154 KeepaliveClient[livekit.NodeID] 155 KeepaliveServer[livekit.NodeID] 156 } 157 158 type keepalivePubSub struct { 159 KeepaliveClient[livekit.NodeID] 160 KeepaliveServer[livekit.NodeID] 161 } 162 163 func NewKeepalivePubSub(params ClientParams) (KeepalivePubSub, error) { 164 client, err := NewKeepaliveClient[livekit.NodeID](params.Bus, params.Options()...) 165 if err != nil { 166 return nil, err 167 } 168 server := must.Get(NewKeepaliveServer[livekit.NodeID](nil, params.Bus)) 169 return &keepalivePubSub{client, server}, nil 170 }