first commit

This commit is contained in:
harshabose
2025-03-08 02:18:29 +05:30
commit 0409463181
12 changed files with 293 additions and 0 deletions
View File
+8
View File
@@ -0,0 +1,8 @@
package client
import "github.com/coder/websocket"
type Client struct {
id string
connection *websocket.Conn
}
+1
View File
@@ -0,0 +1 @@
package user
+42
View File
@@ -0,0 +1,42 @@
package interceptor
type Chain struct {
interceptors []Interceptor
}
func CreateChain(interceptors []Interceptor) *Chain {
return &Chain{interceptors: interceptors}
}
func (chain *Chain) BindIncoming(reader IncomingReader) IncomingReader {
for _, interceptor := range chain.interceptors {
interceptor.BindIncoming(reader)
}
return reader
}
func (chain *Chain) BindOutgoing(writer OutgoingWriter) OutgoingWriter {
for _, interceptor := range chain.interceptors {
interceptor.BindOutgoing(writer)
}
return writer
}
func (chain *Chain) BindConnection(connection Connection) Connection {
for _, interceptor := range chain.interceptors {
interceptor.BindConnection(connection)
}
return connection
}
func (chain *Chain) Close() error {
var errs []error
for _, interceptor := range chain.interceptors {
errs = append(errs, interceptor.Close())
}
return flattenErrs(errs)
}
+52
View File
@@ -0,0 +1,52 @@
package interceptor
import (
"errors"
"strings"
)
func flattenErrs(errs []error) error {
var errs2 []error
for _, e := range errs {
if e != nil {
errs2 = append(errs2, e)
}
}
if len(errs2) == 0 {
return nil
}
return multiError(errs2)
}
type multiError []error
func (me multiError) Error() string {
var errstrings []string
for _, err := range me {
if err != nil {
errstrings = append(errstrings, err.Error())
}
}
if len(errstrings) == 0 {
return "multiError must contain multiple error but is empty"
}
return strings.Join(errstrings, "\n")
}
func (me multiError) Is(err error) bool {
for _, e := range me {
if errors.Is(e, err) {
return true
}
var me2 multiError
if errors.As(e, &me2) {
if me2.Is(err) {
return true
}
}
}
return false
}
+64
View File
@@ -0,0 +1,64 @@
package interceptor
import (
"io"
"github.com/harshabose/skyline_sonata/serve/pkg/message"
)
type Registry struct {
factories []Factory
}
func (registry *Registry) Register(factory Factory) {
registry.factories = append(registry.factories, factory)
}
func (registry *Registry) Build(id string) (Interceptor, error) {
if len(registry.factories) == 0 {
return &NoInterceptor{}, nil
}
interceptors := make([]Interceptor, 0)
for _, factory := range registry.factories {
interceptor, err := factory.NewInterceptor(id)
if err != nil {
return nil, err
}
interceptors = append(interceptors, interceptor)
}
return CreateChain(interceptors), nil
}
// Factory provides an interface for constructing interceptors
type Factory interface {
NewInterceptor(id string) (Interceptor, error)
}
// Interceptor are transformers which bind to incoming, outgoing and connection of a client of the websocket. This can
// be used to add functionalities to the websocket connection.
type Interceptor interface {
// BindIncoming binds to incoming messages to a client
BindIncoming(IncomingReader) IncomingReader
// BindOutgoing binds to outgoing messages from a client
BindOutgoing(OutgoingWriter) OutgoingWriter
// BindConnection binds to the websocket connection itself
BindConnection(Connection) Connection
io.Closer
}
type IncomingReader interface {
Read([]byte) (int, error)
}
type OutgoingWriter interface {
Write(message message.BaseMessage) (int, error)
}
type Connection interface {
}
+19
View File
@@ -0,0 +1,19 @@
package interceptor
type NoInterceptor struct{}
func (interceptor *NoInterceptor) BindIncoming(reader IncomingReader) IncomingReader {
return reader
}
func (interceptor *NoInterceptor) BindOutgoing(writer OutgoingWriter) OutgoingWriter {
return writer
}
func (interceptor *NoInterceptor) BindConnection(connection Connection) Connection {
return connection
}
func (interceptor *NoInterceptor) Close() error {
return nil
}
+14
View File
@@ -0,0 +1,14 @@
package message
type BaseMessage interface {
Marshal() ([]byte, error)
}
type Header struct {
SourceID string `json:"source_id"`
DestinationID string `json:"destination_id"`
}
type Message struct {
Header
}
+1
View File
@@ -0,0 +1 @@
package socket
+3
View File
@@ -0,0 +1,3 @@
package socket
type Option = func(*Socket) error
+8
View File
@@ -0,0 +1,8 @@
package socket
type Settings struct {
}
func RegisterDefaultSettings(settings *Settings) error {
return nil
}
+81
View File
@@ -0,0 +1,81 @@
package socket
import (
"github.com/coder/websocket"
"github.com/harshabose/skyline_sonata/serve/pkg/interceptor"
)
type API struct {
settings *Settings
interceptorRegistry *interceptor.Registry
}
type APIOption = func(*API) error
func WithSocketSettings(settings *Settings) APIOption {
return func(api *API) error {
api.settings = settings
return nil
}
}
func WithInterceptorRegistry(registry *interceptor.Registry) APIOption {
return func(api *API) error {
api.interceptorRegistry = registry
return nil
}
}
func CreateSocketFactory(options ...APIOption) (*API, error) {
api := &API{
settings: nil,
interceptorRegistry: nil,
}
for _, option := range options {
if err := option(api); err != nil {
return nil, err
}
}
if api.settings == nil {
api.settings = &Settings{}
if err := RegisterDefaultSettings(api.settings); err != nil {
return nil, err
}
}
return api, nil
}
func (api *API) CreateWebSocket(id string, options ...Option) (*Socket, error) {
socket := &Socket{
id: id,
}
interceptors, err := api.interceptorRegistry.Build(id)
if err != nil {
return nil, err
}
socket.interceptor = interceptors
for _, option := range options {
if err := option(socket); err != nil {
return nil, err
}
}
return socket, nil
}
type Socket struct {
id string
connections map[string]*websocket.Conn
interceptor interceptor.Interceptor
}
func (socket *Socket) Serve() {
}