github.com/ronaksoft/rony@v0.16.26-0.20230807065236-1743dbfe6959/edge/options.go (about)

     1  package edge
     2  
     3  import (
     4  	"runtime"
     5  	"time"
     6  
     7  	"go.opentelemetry.io/otel/trace"
     8  
     9  	"github.com/ronaksoft/rony"
    10  	"github.com/ronaksoft/rony/errors"
    11  	gossipCluster "github.com/ronaksoft/rony/internal/cluster/gossip"
    12  	dummyGateway "github.com/ronaksoft/rony/internal/gateway/dummy"
    13  	tcpGateway "github.com/ronaksoft/rony/internal/gateway/tcp"
    14  	scyllaRouter "github.com/ronaksoft/rony/internal/router/scylla"
    15  	sqlRouter "github.com/ronaksoft/rony/internal/router/sql"
    16  	udpTunnel "github.com/ronaksoft/rony/internal/tunnel/udp"
    17  	"github.com/ronaksoft/rony/log"
    18  	"github.com/scylladb/gocqlx/v2"
    19  	"gorm.io/gorm"
    20  )
    21  
    22  /*
    23     Creation Time: 2020 - Feb - 22
    24     Created by:  (ehsan)
    25     Maintainers:
    26        1.  Ehsan N. Moosa (E2)
    27     Auditor: Ehsan N. Moosa (E2)
    28     Copyright Ronak Software Group 2020
    29  */
    30  
    31  type Option func(edge *Server)
    32  
    33  func WithTracer(tracer trace.Tracer) Option {
    34  	return func(edge *Server) {
    35  		if tracer == nil {
    36  			return
    37  		}
    38  		edge.tracer = tracer
    39  	}
    40  }
    41  
    42  func WithJSONDispatcher() Option {
    43  	return func(edge *Server) {
    44  		edge.dispatcher = &JSONDispatcher{}
    45  	}
    46  }
    47  
    48  // WithCustomDispatcher enables custom dispatcher to write your specific event handlers.
    49  func WithCustomDispatcher(d Dispatcher) Option {
    50  	return func(edge *Server) {
    51  		if d != nil {
    52  			edge.dispatcher = d
    53  		}
    54  	}
    55  }
    56  
    57  type GossipClusterConfig struct {
    58  	Bootstrap      bool
    59  	ReplicaSet     uint64
    60  	GossipIP       string
    61  	GossipPort     int
    62  	AdvertisedIP   string
    63  	AdvertisedPort int
    64  }
    65  
    66  // WithGossipCluster enables the cluster in gossip mode. This mod is eventually consistent mode but there is
    67  // no need to a central key-value store or any other 3rd party service to run the cluster
    68  func WithGossipCluster(clusterConfig GossipClusterConfig) Option {
    69  	return func(edge *Server) {
    70  		edge.cluster = gossipCluster.New(
    71  			gossipCluster.Config{
    72  				ServerID:       edge.serverID,
    73  				Bootstrap:      clusterConfig.Bootstrap,
    74  				ReplicaSet:     clusterConfig.ReplicaSet,
    75  				GossipPort:     clusterConfig.GossipPort,
    76  				GossipIP:       clusterConfig.GossipIP,
    77  				AdvertisedIP:   clusterConfig.AdvertisedIP,
    78  				AdvertisedPort: clusterConfig.AdvertisedPort,
    79  				Logger:         log.DefaultLogger.With("GossipCluster"),
    80  			},
    81  		)
    82  	}
    83  }
    84  
    85  func WithCustomerCluster(c rony.Cluster) Option {
    86  	return func(edge *Server) {
    87  		edge.cluster = c
    88  	}
    89  }
    90  
    91  type gatewayDelegate struct {
    92  	edge *Server
    93  }
    94  
    95  func (g gatewayDelegate) OnConnect(c rony.Conn, kvs ...*rony.KeyValue) {
    96  	g.edge.onGatewayConnect(c, kvs...)
    97  }
    98  
    99  func (g gatewayDelegate) OnMessage(c rony.Conn, streamID int64, data []byte) {
   100  	g.edge.onGatewayMessage(c, streamID, data)
   101  }
   102  
   103  func (g gatewayDelegate) OnClose(c rony.Conn) {
   104  	g.edge.onGatewayClose(c)
   105  }
   106  
   107  type TcpGatewayConfig struct {
   108  	Concurrency   int
   109  	ListenAddress string
   110  	MaxBodySize   int
   111  	MaxIdleTime   time.Duration
   112  	Protocol      rony.GatewayProtocol
   113  	ExternalAddrs []string
   114  	TextDataFrame bool
   115  }
   116  
   117  // WithTcpGateway set the gateway to tcp which can support http and/or websocket
   118  // Only one gateway could be set and if you set another gateway it panics on runtime.
   119  func WithTcpGateway(gatewayConfig TcpGatewayConfig) Option {
   120  	return func(edge *Server) {
   121  		if edge.gateway != nil {
   122  			panic(errors.ErrGatewayAlreadyInitialized)
   123  		}
   124  		if gatewayConfig.Protocol == rony.Undefined {
   125  			gatewayConfig.Protocol = rony.TCP
   126  		}
   127  		if gatewayConfig.Concurrency == 0 {
   128  			gatewayConfig.Concurrency = runtime.NumCPU() * 100
   129  		}
   130  		gatewayTcp, err := tcpGateway.New(tcpGateway.Config{
   131  			Concurrency:   gatewayConfig.Concurrency,
   132  			ListenAddress: gatewayConfig.ListenAddress,
   133  			MaxBodySize:   gatewayConfig.MaxBodySize,
   134  			MaxIdleTime:   gatewayConfig.MaxIdleTime,
   135  			Protocol:      gatewayConfig.Protocol,
   136  			ExternalAddrs: gatewayConfig.ExternalAddrs,
   137  			Logger:        log.DefaultLogger.With("TCPGateway"),
   138  			TextDataFrame: gatewayConfig.TextDataFrame,
   139  		})
   140  		if err != nil {
   141  			panic(err)
   142  		}
   143  
   144  		gatewayTcp.Subscribe(&gatewayDelegate{edge: edge})
   145  		edge.gateway = gatewayTcp
   146  	}
   147  }
   148  
   149  type DummyGatewayConfig = dummyGateway.Config
   150  
   151  // WithTestGateway set the gateway to a dummy gateway which is useful for writing tests.
   152  // Only one gateway could be set and if you set another gateway it panics on runtime.
   153  func WithTestGateway(gatewayConfig DummyGatewayConfig) Option {
   154  	return func(edge *Server) {
   155  		if edge.gateway != nil {
   156  			panic(errors.ErrGatewayAlreadyInitialized)
   157  		}
   158  		gatewayDummy, err := dummyGateway.New(gatewayConfig)
   159  		if err != nil {
   160  			panic(err)
   161  		}
   162  		gatewayDummy.Subscribe(&gatewayDelegate{edge: edge})
   163  		edge.gateway = gatewayDummy
   164  	}
   165  }
   166  
   167  func WithCustomGateway(gateway rony.Gateway) Option {
   168  	return func(edge *Server) {
   169  		if edge.gateway != nil {
   170  			panic(errors.ErrGatewayAlreadyInitialized)
   171  		}
   172  
   173  		gateway.Subscribe(&gatewayDelegate{edge: edge})
   174  		edge.gateway = gateway
   175  	}
   176  }
   177  
   178  type UdpTunnelConfig struct {
   179  	ListenAddress string
   180  	MaxBodySize   int
   181  	ExternalAddrs []string
   182  }
   183  
   184  // WithUdpTunnel set the tunnel to a udp based tunnel which provides communication channel between
   185  // edge servers.
   186  func WithUdpTunnel(config UdpTunnelConfig) Option {
   187  	return func(edge *Server) {
   188  		tunnelUDP, err := udpTunnel.New(udpTunnel.Config{
   189  			ServerID:      edge.GetServerID(),
   190  			ListenAddress: config.ListenAddress,
   191  			MaxBodySize:   config.MaxBodySize,
   192  			ExternalAddrs: config.ExternalAddrs,
   193  			Logger:        log.DefaultLogger.With("Tunnel"),
   194  		})
   195  		if err != nil {
   196  			panic(err)
   197  		}
   198  		tunnelUDP.MessageHandler = edge.onTunnelMessage
   199  		edge.tunnel = tunnelUDP
   200  	}
   201  }
   202  
   203  func WithCustomRouter(r rony.Router) Option {
   204  	return func(edge *Server) {
   205  		edge.router = r
   206  	}
   207  }
   208  
   209  type ScyllaRouterConfig struct {
   210  	DbSession gocqlx.Session
   211  }
   212  
   213  func WithScyllaRouter(config ScyllaRouterConfig) Option {
   214  	return func(edge *Server) {
   215  		edge.router = scyllaRouter.New(config.DbSession)
   216  	}
   217  }
   218  
   219  type SqlRouterConfig struct {
   220  	DB *gorm.DB
   221  }
   222  
   223  func WithSqlRouter(config SqlRouterConfig) Option {
   224  	return func(edge *Server) {
   225  		edge.router = sqlRouter.New(config.DB)
   226  	}
   227  }