Class: Restate::Endpoint

Inherits:
Object
  • Object
show all
Defined in:
lib/restate/endpoint.rb

Overview

Container for registered services. Bind services here, then create the Rack app.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeEndpoint

Returns a new instance of Endpoint.



11
12
13
14
15
16
17
# File 'lib/restate/endpoint.rb', line 11

def initialize
  @services = {}
  @protocol = nil
  @identity_keys = []
  @middleware = []
  @outbound_middleware = []
end

Instance Attribute Details

#identity_keysObject (readonly)

Returns the value of attribute identity_keys.



7
8
9
# File 'lib/restate/endpoint.rb', line 7

def identity_keys
  @identity_keys
end

#middlewareObject (readonly)

Returns the value of attribute middleware.



7
8
9
# File 'lib/restate/endpoint.rb', line 7

def middleware
  @middleware
end

#outbound_middlewareObject (readonly)

Returns the value of attribute outbound_middleware.



7
8
9
# File 'lib/restate/endpoint.rb', line 7

def outbound_middleware
  @outbound_middleware
end

#protocolObject

Returns the value of attribute protocol.



9
10
11
# File 'lib/restate/endpoint.rb', line 9

def protocol
  @protocol
end

#servicesObject (readonly)

Returns the value of attribute services.



7
8
9
# File 'lib/restate/endpoint.rb', line 7

def services
  @services
end

Instance Method Details

#appObject

Build and return the Rack-compatible application.



135
136
137
138
# File 'lib/restate/endpoint.rb', line 135

def app
  require_relative 'server'
  Server.new(self)
end

#bind(*svcs) ⇒ self

Bind one or more services to this endpoint.

Parameters:

Returns:

  • (self)

Raises:

  • (ArgumentError)

    if a service with the same name is already bound



24
25
26
27
28
29
30
31
32
# File 'lib/restate/endpoint.rb', line 24

def bind(*svcs)
  svcs.each do |svc|
    svc_name = svc.service_name
    raise ArgumentError, "Service #{svc_name} already exists" if @services.key?(svc_name)

    @services[svc_name] = svc
  end
  self
end

#identity_key(key) ⇒ Object

Add an identity key for request verification.



47
48
49
50
# File 'lib/restate/endpoint.rb', line 47

def identity_key(key)
  @identity_keys << key
  self
end

#request_response_protocolObject

Force request/response protocol.



41
42
43
44
# File 'lib/restate/endpoint.rb', line 41

def request_response_protocol
  @protocol = 'request_response'
  self
end

#streaming_protocolObject

Force bidirectional streaming protocol.



35
36
37
38
# File 'lib/restate/endpoint.rb', line 35

def streaming_protocol
  @protocol = 'bidi'
  self
end

#use(klass, *args, **kwargs) ⇒ self

Add inbound (server) middleware.

Inbound middleware wraps every handler invocation, like Sidekiq server middleware.

A middleware is a class whose instances respond to call(handler, ctx). Use yield inside call to invoke the next middleware or the handler. The return value of yield is the handler’s return value.

Examples:

OpenTelemetry tracing

class TracingMiddleware
  def call(handler, ctx)
    extracted = OpenTelemetry.propagation.extract(ctx.request.headers)
    OpenTelemetry::Context.with_current(extracted) do
      tracer.in_span(handler.name) { yield }
    end
  end
end
endpoint.use(TracingMiddleware)

Metrics

class MetricsMiddleware
  def call(handler, ctx)
    start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
    result = yield
    duration = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start
    StatsD.timing("restate.handler.#{handler.name}", duration)
    result
  end
end
endpoint.use(MetricsMiddleware)

Parameters:

  • klass (Class)

    middleware class (will be instantiated by the SDK)

  • args (Array)

    positional arguments for the middleware constructor

  • kwargs (Hash)

    keyword arguments for the middleware constructor

Returns:

  • (self)


88
89
90
91
# File 'lib/restate/endpoint.rb', line 88

def use(klass, *args, **kwargs)
  @middleware << instantiate_middleware(klass, args, kwargs)
  self
end

#use_outbound(klass, *args, **kwargs) ⇒ self

Add outbound (client) middleware.

Outbound middleware wraps every outgoing service call and send, like Sidekiq client middleware.

A middleware is a class whose instances respond to call(service, handler, headers). The headers hash is mutable — modify it to attach headers to the outgoing request. Use yield to continue the chain.

Note: Restate automatically propagates inbound headers to outbound calls. Outbound middleware is for injecting new headers that aren’t on the original request (e.g., tenant IDs from fiber-local storage, authorization tokens for specific target services).

Examples:

Propagate tenant ID to all outgoing calls

class TenantOutboundMiddleware
  def call(_service, _handler, headers)
    headers['x-tenant-id'] = Thread.current[:tenant_id]
    yield
  end
end
endpoint.use_outbound(TenantOutboundMiddleware)

Log all outgoing calls

class OutboundLogger
  def call(service, handler, headers)
    logger.info("Calling #{service}/#{handler}")
    yield
  end
end
endpoint.use_outbound(OutboundLogger)

Parameters:

  • klass (Class)

    middleware class (will be instantiated by the SDK)

  • args (Array)

    positional arguments for the middleware constructor

  • kwargs (Hash)

    keyword arguments for the middleware constructor

Returns:

  • (self)


129
130
131
132
# File 'lib/restate/endpoint.rb', line 129

def use_outbound(klass, *args, **kwargs)
  @outbound_middleware << instantiate_middleware(klass, args, kwargs)
  self
end