feat(maitred): Update maitred - hookup to the API (#198)

## Description
We are attempting to hookup maitred to the API
Maitred duties will be:
- [ ] Hookup to the API
- [ ]  Wait for signal (from the API) to start Steam
- [ ] Stop signal to stop the gaming session, clean up Steam... and
maybe do the backup

## Summary by CodeRabbit

- **New Features**
- Introduced Docker-based deployment configurations for both the main
and relay applications.
- Added new API endpoints enabling real-time machine messaging and
enhanced IoT operations.
- Expanded database schema and actor types to support improved machine
tracking.

- **Improvements**
- Enhanced real-time communication and relay management with streamlined
room handling.
- Upgraded dependencies, logging, and error handling for greater
stability and performance.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: DatCaptainHorse <DatCaptainHorse@users.noreply.github.com>
Co-authored-by: Kristian Ollikainen <14197772+DatCaptainHorse@users.noreply.github.com>
This commit is contained in:
Wanjohi
2025-04-07 23:23:53 +03:00
committed by GitHub
parent 6990494b34
commit de80f3e6ab
84 changed files with 7357 additions and 1331 deletions

View File

@@ -0,0 +1,101 @@
package common
import (
"errors"
"reflect"
"sync"
)
var (
ErrKeyNotFound = errors.New("key not found")
ErrValueNotPointer = errors.New("value is not a pointer")
ErrFieldNotFound = errors.New("field not found")
ErrTypeMismatch = errors.New("type mismatch")
)
// SafeMap is a generic thread-safe map with its own mutex
type SafeMap[K comparable, V any] struct {
mu sync.RWMutex
m map[K]V
}
// NewSafeMap creates a new SafeMap instance
func NewSafeMap[K comparable, V any]() *SafeMap[K, V] {
return &SafeMap[K, V]{
m: make(map[K]V),
}
}
// Get retrieves a value from the map
func (sm *SafeMap[K, V]) Get(key K) (V, bool) {
sm.mu.RLock()
defer sm.mu.RUnlock()
v, ok := sm.m[key]
return v, ok
}
// Set adds or updates a value in the map
func (sm *SafeMap[K, V]) Set(key K, value V) {
sm.mu.Lock()
defer sm.mu.Unlock()
sm.m[key] = value
}
// Delete removes a key from the map
func (sm *SafeMap[K, V]) Delete(key K) {
sm.mu.Lock()
defer sm.mu.Unlock()
delete(sm.m, key)
}
// Len returns the number of items in the map
func (sm *SafeMap[K, V]) Len() int {
sm.mu.RLock()
defer sm.mu.RUnlock()
return len(sm.m)
}
// Copy creates a shallow copy of the map and returns it
func (sm *SafeMap[K, V]) Copy() map[K]V {
sm.mu.RLock()
defer sm.mu.RUnlock()
copied := make(map[K]V, len(sm.m))
for k, v := range sm.m {
copied[k] = v
}
return copied
}
// Update updates a specific field in the value data
func (sm *SafeMap[K, V]) Update(key K, fieldName string, newValue any) error {
sm.mu.Lock()
defer sm.mu.Unlock()
v, ok := sm.m[key]
if !ok {
return ErrKeyNotFound
}
// Use reflect to update the field
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
return ErrValueNotPointer
}
rv = rv.Elem()
// Check if the field exists
field := rv.FieldByName(fieldName)
if !field.IsValid() || !field.CanSet() {
return ErrFieldNotFound
}
newRV := reflect.ValueOf(newValue)
if newRV.Type() != field.Type() {
return ErrTypeMismatch
}
field.Set(newRV)
sm.m[key] = v
return nil
}