Class: MudisServer

Inherits:
Object
  • Object
show all
Includes:
MudisIPCConfig
Defined in:
lib/mudis_server.rb

Overview

Socket server for handling Mudis operations via IPC mode Automatically uses UNIX sockets on Linux/macOS and TCP on Windows

Constant Summary collapse

COMMANDS =

Define command handlers mapping Each command maps to a lambda that takes a request hash and performs the corresponding Mudis operation.

{
  "read"          => ->(r) { Mudis.read(r[:key], namespace: r[:namespace]) },
  "write"         => ->(r) { Mudis.write(r[:key], r[:value], expires_in: r[:ttl], namespace: r[:namespace]) },
  "delete"        => ->(r) { Mudis.delete(r[:key], namespace: r[:namespace]) },
  "exists"        => ->(r) { Mudis.exists?(r[:key], namespace: r[:namespace]) },
  "fetch"         => ->(r) { Mudis.fetch(r[:key], expires_in: r[:ttl], namespace: r[:namespace]) { r[:fallback] } },
  "metrics"       => ->(_) { Mudis.metrics },
  "reset_metrics" => ->(_) { Mudis.reset_metrics! },
  "reset"         => ->(_) { Mudis.reset! }
}.freeze

Constants included from MudisIPCConfig

MudisIPCConfig::SOCKET_PATH, MudisIPCConfig::TCP_HOST, MudisIPCConfig::TCP_PORT

Class Method Summary collapse

Methods included from MudisIPCConfig

use_tcp?

Class Method Details

.accept_connections(server) ⇒ Object

Accept connections in a loop (works for both TCP and UNIX)



55
56
57
58
59
60
61
62
63
64
# File 'lib/mudis_server.rb', line 55

def self.accept_connections(server)
  Thread.new do
    loop do
      client = server.accept
      Thread.new(client) do |sock|
        handle_client(sock)
      end
    end
  end
end

.handle_client(socket) ⇒ void

This method returns an undefined value.

Handle a single client connection Reads the request, processes it, and sends back the response

Parameters:

  • socket (Socket)

    The client socket (TCP or UNIX)



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/mudis_server.rb', line 70

def self.handle_client(socket)
  request = JSON.parse(socket.gets, symbolize_names: true)
  return unless request

  response = process_request(request)
  write_response(socket, ok: true, value: response)
rescue StandardError => e
  write_response(socket, ok: false, error: e.message)
ensure
  socket.close
end

.process_request(req) ⇒ Object

Process a request hash and return the result Raises an error if the command is unknown

Parameters:

  • req (Hash)

    The request hash containing :cmd and other parameters

Returns:

  • (Object)

    The result of the command execution



86
87
88
89
90
91
# File 'lib/mudis_server.rb', line 86

def self.process_request(req)
  handler = COMMANDS[req[:cmd]]
  raise "Unknown command: #{req[:cmd]}" unless handler

  handler.call(req)
end

.start!Object

Start the MudisServer Automatically selects TCP on Windows, UNIX sockets elsewhere This will run in a separate thread and handle incoming client connections.



29
30
31
32
33
34
35
# File 'lib/mudis_server.rb', line 29

def self.start!
  if MudisIPCConfig.use_tcp?
    start_tcp_server!
  else
    start_unix_server!
  end
end

.start_tcp_server!Object

Start TCP server (for Windows or development)



38
39
40
41
42
43
# File 'lib/mudis_server.rb', line 38

def self.start_tcp_server!
  warn "[MudisServer] Using TCP mode - recommended for development only"
  server = TCPServer.new(TCP_HOST, TCP_PORT)
  puts "[MudisServer] Listening on TCP #{TCP_HOST}:#{TCP_PORT}"
  accept_connections(server)
end

.start_unix_server!Object

Start UNIX socket server (production mode for Linux/macOS)



46
47
48
49
50
51
52
# File 'lib/mudis_server.rb', line 46

def self.start_unix_server! # rubocop:disable Metrics/MethodLength
  File.unlink(SOCKET_PATH) if File.exist?(SOCKET_PATH)
  server = UNIXServer.new(SOCKET_PATH)
  server.listen(128)
  puts "[MudisServer] Listening on UNIX socket #{SOCKET_PATH}"
  accept_connections(server)
end

.write_response(socket, payload) ⇒ void

This method returns an undefined value.

Write a response to the client socket

Parameters:

  • socket (Socket)

    The client socket

  • payload (Hash)

    The response payload



97
98
99
# File 'lib/mudis_server.rb', line 97

def self.write_response(socket, payload)
  socket.puts(JSON.dump(payload))
end