Gateway working, beta
This commit is contained in:
91
util/cache/cache.go
vendored
91
util/cache/cache.go
vendored
@@ -1,91 +0,0 @@
|
||||
package cache
|
||||
|
||||
func NewCache() *Cache {
|
||||
c := &Cache{}
|
||||
c.state.Store(&mappings{
|
||||
s2c: make(map[string]string),
|
||||
c2s: make(map[string]string),
|
||||
})
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Cache) Set(serverId, channelId string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
current := c.state.Load()
|
||||
next := current.clone()
|
||||
|
||||
if oldCh, ok := next.s2c[serverId]; ok && oldCh != channelId {
|
||||
delete(next.c2s, oldCh)
|
||||
}
|
||||
if oldSrv, ok := next.c2s[channelId]; ok && oldSrv != serverId {
|
||||
delete(next.s2c, oldSrv)
|
||||
}
|
||||
|
||||
next.s2c[serverId] = channelId
|
||||
next.c2s[channelId] = serverId
|
||||
|
||||
c.state.Store(next)
|
||||
}
|
||||
|
||||
func (c *Cache) GetByServerId(serverId string) (string, bool) {
|
||||
m := c.state.Load()
|
||||
val, ok := m.s2c[serverId]
|
||||
return val, ok
|
||||
}
|
||||
|
||||
func (c *Cache) GetByChannelId(channelId string) (string, bool) {
|
||||
m := c.state.Load()
|
||||
val, ok := m.c2s[channelId]
|
||||
return val, ok
|
||||
}
|
||||
|
||||
func (c *Cache) RemoveByServerId(serverId string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
current := c.state.Load()
|
||||
if _, ok := current.s2c[serverId]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
next := current.clone()
|
||||
if channelId, ok := next.s2c[serverId]; ok {
|
||||
delete(next.s2c, serverId)
|
||||
delete(next.c2s, channelId)
|
||||
}
|
||||
c.state.Store(next)
|
||||
}
|
||||
|
||||
func (c *Cache) RemoveByChannelId(channelId string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
current := c.state.Load()
|
||||
if _, ok := current.c2s[channelId]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
next := current.clone()
|
||||
if serverId, ok := next.c2s[channelId]; ok {
|
||||
delete(next.c2s, channelId)
|
||||
delete(next.s2c, serverId)
|
||||
}
|
||||
c.state.Store(next)
|
||||
}
|
||||
|
||||
func (m *mappings) clone() *mappings {
|
||||
newM := &mappings{
|
||||
s2c: make(map[string]string, len(m.s2c)),
|
||||
c2s: make(map[string]string, len(m.c2s)),
|
||||
}
|
||||
for k, v := range m.s2c {
|
||||
newM.s2c[k] = v
|
||||
}
|
||||
for k, v := range m.c2s {
|
||||
newM.c2s[k] = v
|
||||
}
|
||||
return newM
|
||||
}
|
||||
88
util/cache/conn_cache.go
vendored
88
util/cache/conn_cache.go
vendored
@@ -1,88 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
func NewConnectionCache() *ConnectionCache {
|
||||
c := &ConnectionCache{}
|
||||
c.state.Store(&connectionMappings{
|
||||
id2c: make(map[string]*conn),
|
||||
})
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ConnectionCache) Set(id string, connection *websocket.Conn, meta *ConnectionMetaData) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
current := c.state.Load()
|
||||
next := current.clone()
|
||||
|
||||
next.id2c[id] = &conn{
|
||||
connection: connection,
|
||||
meta: meta,
|
||||
}
|
||||
|
||||
c.state.Store(next)
|
||||
}
|
||||
|
||||
func (c *ConnectionCache) GetById(id string) (*websocket.Conn, *ConnectionMetaData, bool) {
|
||||
m := c.state.Load()
|
||||
if conn, ok := m.id2c[id]; ok {
|
||||
return conn.connection, conn.meta, true
|
||||
}
|
||||
|
||||
return nil, nil, false
|
||||
}
|
||||
|
||||
func (c *ConnectionCache) RemoveById(id string) {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
current := c.state.Load()
|
||||
if _, ok := current.id2c[id]; !ok {
|
||||
return
|
||||
}
|
||||
|
||||
next := current.clone()
|
||||
delete(next.id2c, id)
|
||||
|
||||
c.state.Store(next)
|
||||
}
|
||||
|
||||
func (c *ConnectionCache) Range(fn func(id string, connection *websocket.Conn, meta *ConnectionMetaData)) {
|
||||
m := c.state.Load()
|
||||
for id, conn := range m.id2c {
|
||||
fn(id, conn.connection, conn.meta)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ConnectionCache) GetAllConnections() []*websocket.Conn {
|
||||
m := c.state.Load()
|
||||
conns := make([]*websocket.Conn, 0, len(m.id2c))
|
||||
for _, conn := range m.id2c {
|
||||
conns = append(conns, conn.connection)
|
||||
}
|
||||
return conns
|
||||
}
|
||||
|
||||
func (c *ConnectionCache) Clear() {
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
||||
c.state.Store(&connectionMappings{
|
||||
id2c: make(map[string]*conn),
|
||||
})
|
||||
}
|
||||
|
||||
func (cm *connectionMappings) clone() *connectionMappings {
|
||||
newCM := &connectionMappings{
|
||||
id2c: make(map[string]*conn, len(cm.id2c)),
|
||||
}
|
||||
for k, v := range cm.id2c {
|
||||
newCM.id2c[k] = v
|
||||
}
|
||||
return newCM
|
||||
}
|
||||
37
util/cache/structs.go
vendored
37
util/cache/structs.go
vendored
@@ -1,37 +0,0 @@
|
||||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type Cache struct {
|
||||
mu sync.Mutex
|
||||
state atomic.Pointer[mappings]
|
||||
}
|
||||
|
||||
type ConnectionCache struct {
|
||||
mu sync.Mutex
|
||||
state atomic.Pointer[connectionMappings]
|
||||
}
|
||||
|
||||
type mappings struct {
|
||||
s2c map[string]string
|
||||
c2s map[string]string
|
||||
}
|
||||
|
||||
type connectionMappings struct {
|
||||
id2c map[string]*conn
|
||||
}
|
||||
|
||||
type ConnectionMetaData struct {
|
||||
ConnectionType string // "mod" or "bot"
|
||||
ID string // server_id or bot_id for logging
|
||||
}
|
||||
|
||||
type conn struct {
|
||||
connection *websocket.Conn
|
||||
meta *ConnectionMetaData
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package queue
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Queue is a thin wrapper around a buffered channel.
|
||||
type Queue[T any] struct {
|
||||
ch chan T
|
||||
closedMu sync.Mutex
|
||||
closed bool
|
||||
closedCh chan struct{}
|
||||
}
|
||||
|
||||
func NewQueue[T any](capacity int) *Queue[T] {
|
||||
if capacity <= 0 {
|
||||
panic("capacity > 0 required")
|
||||
}
|
||||
|
||||
return &Queue[T]{
|
||||
ch: make(chan T, capacity),
|
||||
closedCh: make(chan struct{}),
|
||||
}
|
||||
}
|
||||
|
||||
// Cap returns capacity.
|
||||
func (q *Queue[T]) Cap() int { return cap(q.ch) }
|
||||
|
||||
// Len returns current length (snapshot).
|
||||
func (q *Queue[T]) Len() int { return len(q.ch) }
|
||||
|
||||
// Enqueue returns immediately: true if enqueued, false otherwise.
|
||||
func (q *Queue[T]) Enqueue(v T) bool {
|
||||
select {
|
||||
case q.ch <- v:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Dequeue returns immediately (item, true) or (zero, false) if empty.
|
||||
func (q *Queue[T]) Dequeue() (T, bool) {
|
||||
var zero T
|
||||
select {
|
||||
case v := <-q.ch:
|
||||
return v, true
|
||||
default:
|
||||
return zero, false
|
||||
}
|
||||
}
|
||||
|
||||
// Close closes the queue. Further Enqueue attempts return ErrClosed. Consumers drain until channel empty then see ErrClosed.
|
||||
func (q *Queue[T]) Close() {
|
||||
q.closedMu.Lock()
|
||||
|
||||
if q.closed {
|
||||
q.closedMu.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
q.closed = true
|
||||
close(q.closedCh)
|
||||
close(q.ch)
|
||||
q.closedMu.Unlock()
|
||||
}
|
||||
Reference in New Issue
Block a user