actor

package
v0.0.0-...-2715f90 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 18, 2024 License: Apache-2.0 Imports: 20 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	TerminatedReason_name = map[int32]string{
		0: "Stopped",
		1: "AddressTerminated",
		2: "NotFound",
	}
	TerminatedReason_value = map[string]int32{
		"Stopped":           0,
		"AddressTerminated": 1,
		"NotFound":          2,
	}
)

Enum value maps for TerminatedReason.

View Source
var (
	// ErrNameExists is the error used when an existing name is used for spawning an actor.
	ErrNameExists = errors.New("spawn: name exists")

	// ErrTimeout is the error used when a future times out before receiving a result.
	ErrTimeout = errors.New("future: timeout")

	// ErrDeadLetter is meaning you request to a unreachable PID.
	ErrDeadLetter = errors.New("future: dead letter")
)
View Source
var EmptyMessageHeader = make(messageHeader)
View Source
var File_actor_proto protoreflect.FileDescriptor

Functions

func UnwrapEnvelope

func UnwrapEnvelope(message interface{}) (ReadonlyMessageHeader, interface{}, *PID)

func UnwrapEnvelopeMessage

func UnwrapEnvelopeMessage(message interface{}) interface{}

Types

type Actor

type Actor interface {
	Receive(c Context)
}

Actor is the interface that defines the Receive method.

Receive is sent messages to be processed from the mailbox associated with the instance of the actor

type ActorProcess

type ActorProcess struct {
	// contains filtered or unexported fields
}

func NewActorProcess

func NewActorProcess(mailbox Mailbox) *ActorProcess

func (*ActorProcess) SendSystemMessage

func (ref *ActorProcess) SendSystemMessage(_ *PID, message SystemMessage)

func (*ActorProcess) SendUserMessage

func (ref *ActorProcess) SendUserMessage(_ *PID, message *MessageEnvelope)

func (*ActorProcess) Stop

func (ref *ActorProcess) Stop(pid *PID)

type ActorSystem

type ActorSystem struct {
	ProcessRegistry *ProcessRegistry
	Root            *RootContext
	EventStream     *EventStream
	DeadLetter      *deadLetter
	Config          *Config

	ID string
	// contains filtered or unexported fields
}

func NewActorSystem

func NewActorSystem(opts ...ConfigOption) *ActorSystem

func NewActorSystemWithConfig

func NewActorSystemWithConfig(config *Config) *ActorSystem

func (*ActorSystem) Address

func (as *ActorSystem) Address() string

func (*ActorSystem) IsStopped

func (as *ActorSystem) IsStopped() bool

func (*ActorSystem) Logger

func (as *ActorSystem) Logger() *slog.Logger

func (*ActorSystem) NewLocalPID

func (as *ActorSystem) NewLocalPID(id string) *PID

func (*ActorSystem) Shutdown

func (as *ActorSystem) Shutdown()

type AutoReceiveMessage

type AutoReceiveMessage interface {
	AutoReceiveMessage()
}

An AutoReceiveMessage is a special kind of user message that will be handled in some way automatically by the actor

type Config

type Config struct {
	LoggerFactory func(system *ActorSystem) *slog.Logger
}

func Configure

func Configure(options ...ConfigOption) *Config

type ConfigOption

type ConfigOption func(config *Config)

func WithLoggerFactory

func WithLoggerFactory(factory func(system *ActorSystem) *slog.Logger) ConfigOption

WithLoggerFactory sets the logger factory to use for the actor system

type Context

type Context interface {
	// contains filtered or unexported methods
}

type ContextDecoratorFunc

type ContextDecoratorFunc func(ctx Context) Context

type DeadLetterEvent

type DeadLetterEvent struct {
	PID     *PID // nonexistent PID
	Message interface{}
	Sender  *PID // 发送者
}

DeadLetterEvent 当有消息发送给一个不存在的 PID 时。 发布事件给所有的订阅者

func (*DeadLetterEvent) EventMessage

func (d *DeadLetterEvent) EventMessage()

type DeadLetterResponse

type DeadLetterResponse struct {
	Target *PID `protobuf:"bytes,1,opt,name=Target,proto3" json:"Target,omitempty"`
	// contains filtered or unexported fields
}

func (*DeadLetterResponse) Descriptor deprecated

func (*DeadLetterResponse) Descriptor() ([]byte, []int)

Deprecated: Use DeadLetterResponse.ProtoReflect.Descriptor instead.

func (*DeadLetterResponse) GetTarget

func (x *DeadLetterResponse) GetTarget() *PID

func (*DeadLetterResponse) ProtoMessage

func (*DeadLetterResponse) ProtoMessage()

func (*DeadLetterResponse) ProtoReflect

func (x *DeadLetterResponse) ProtoReflect() protoreflect.Message

func (*DeadLetterResponse) Reset

func (x *DeadLetterResponse) Reset()

func (*DeadLetterResponse) String

func (x *DeadLetterResponse) String() string

type Dispatcher

type Dispatcher interface {
	Schedule(fn func())
	Throughput() int
}

func NewDefaultDispatcher

func NewDefaultDispatcher(throughput int) Dispatcher

func NewSynchronizedDispatcher

func NewSynchronizedDispatcher(throughput int) Dispatcher

type EventMessage

type EventMessage interface {
	EventMessage()
}

type EventStream

type EventStream struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

func NewEventStream

func NewEventStream() *EventStream

func (*EventStream) Length

func (es *EventStream) Length() int

func (*EventStream) Publish

func (es *EventStream) Publish(evt EventMessage)

func (*EventStream) Subscribe

func (es *EventStream) Subscribe(handler Handler) *Subscription

Subscribe the given handler to the EventStream

func (*EventStream) Unsubscribe

func (es *EventStream) Unsubscribe(sub *Subscription)

type Failure

type Failure struct {
	Who    *PID
	Reason interface{}
	//RestartStats *RestartStatistics
	Message interface{}
}

Failure message is sent to an actor parent when an exception is thrown by one of its methods

func (*Failure) SystemMessage

func (*Failure) SystemMessage()

type Future

type Future struct {
	// contains filtered or unexported fields
}

func NewFuture

func NewFuture(actorSystem *ActorSystem, d time.Duration) *Future

NewFuture creates and returns a new actor.Future with a timeout of duration d.

func (*Future) PID

func (f *Future) PID() *PID

PID to the backing actor for the Future result.

func (*Future) PipeTo

func (f *Future) PipeTo(pids ...*PID)

PipeTo forwards the result or error of the future to the specified pids.

func (*Future) Result

func (f *Future) Result() (*MessageEnvelope, error)

Result waits for the future to resolve.

func (*Future) Wait

func (f *Future) Wait() error

type Handler

type Handler func(evt EventMessage)

Handler defines a callback function that must be pass when subscribing.

type Invoker

type Invoker interface {
	InvokeSystemMessage(message SystemMessage)
	InvokeUserMessage(envelope *MessageEnvelope)
	EscalateFailure(reason interface{}, message interface{})
}

Invoker is the interface used by a mailbox to forward messages for processing

type Mailbox

type Mailbox interface {
	Start()
	Count() int
	PostUserMessage(message *MessageEnvelope)
	PostSystemMessage(message SystemMessage)
	RegisterHandlers(invoker Invoker, dispatcher Dispatcher)
}

type MailboxMiddleware

type MailboxMiddleware interface {
	MailboxStarted()
	MessagePosted(message interface{})
	MessageReceived(message interface{})
	MailboxEmpty()
}

MailboxMiddleware is an interface for intercepting messages and events in the mailbox

type MailboxProducer

type MailboxProducer func() Mailbox

MailboxProducer is a function which creates a new mailbox

func UnboundedLockfree

func UnboundedLockfree(mailboxStats ...MailboxMiddleware) MailboxProducer

UnboundedLockfree returns a producer which creates an unbounded, lock-free mailbox. This mailbox is cheaper to allocate, but has a slower throughput than the plain Unbounded mailbox.

type MessageEnvelope

type MessageEnvelope struct {
	Header  messageHeader
	Message interface{}
	Sender  *PID
}

func PoisonPillMessage

func PoisonPillMessage() *MessageEnvelope

func WrapEnvelopWithSender

func WrapEnvelopWithSender(message interface{}, sender *PID) *MessageEnvelope

func WrapEnvelope

func WrapEnvelope(message interface{}) *MessageEnvelope

func (*MessageEnvelope) GetHeader

func (envelope *MessageEnvelope) GetHeader(key string) string

func (*MessageEnvelope) SetHeader

func (envelope *MessageEnvelope) SetHeader(key string, value string)

type NotInfluenceReceiveTimeout

type NotInfluenceReceiveTimeout interface {
	NotInfluenceReceiveTimeout()
}

NotInfluenceReceiveTimeout messages will not reset the ReceiveTimeout timer of an actor that receives the message

type PID

type PID struct {
	Address   string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
	ID        string `protobuf:"bytes,2,opt,name=ID,proto3" json:"ID,omitempty"`
	RequestId uint32 `protobuf:"varint,3,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"`
	// contains filtered or unexported fields
}

func NewPID

func NewPID(address, id string) *PID

func (*PID) Descriptor deprecated

func (*PID) Descriptor() ([]byte, []int)

Deprecated: Use PID.ProtoReflect.Descriptor instead.

func (*PID) Equal

func (pid *PID) Equal(other *PID) bool

func (*PID) GetAddress

func (x *PID) GetAddress() string

func (*PID) GetID

func (x *PID) GetID() string

func (*PID) GetRequestId

func (x *PID) GetRequestId() uint32

func (*PID) ProtoMessage

func (*PID) ProtoMessage()

func (*PID) ProtoReflect

func (x *PID) ProtoReflect() protoreflect.Message

func (*PID) Reset

func (x *PID) Reset()

func (*PID) String

func (x *PID) String() string

type PIDSet

type PIDSet struct {
	// contains filtered or unexported fields
}

func NewPIDSet

func NewPIDSet(pids ...*PID) *PIDSet

NewPIDSet returns a new PIDSet with the given pids.

func (*PIDSet) Add

func (p *PIDSet) Add(v *PID)

Add adds the element v to the set.

func (*PIDSet) Clear

func (p *PIDSet) Clear()

Clear removes all the elements in the set.

func (*PIDSet) Clone

func (p *PIDSet) Clone() *PIDSet

func (*PIDSet) Contains

func (p *PIDSet) Contains(v *PID) bool

func (*PIDSet) Empty

func (p *PIDSet) Empty() bool

Empty reports whether the set is empty.

func (*PIDSet) ForEach

func (p *PIDSet) ForEach(f func(i int, pid *PID))

ForEach invokes f for every element of the set.

func (*PIDSet) Get

func (p *PIDSet) Get(index int) *PID

func (*PIDSet) Len

func (p *PIDSet) Len() int

Len returns the number of elements in the set.

func (*PIDSet) Remove

func (p *PIDSet) Remove(v *PID) bool

Remove removes v from the set and returns true if them element existed.

func (*PIDSet) Values

func (p *PIDSet) Values() []*PID

Values returns all the elements of the set as a slice.

type PoisonPill

type PoisonPill struct {
	// contains filtered or unexported fields
}

user messages

func (*PoisonPill) AutoReceiveMessage

func (*PoisonPill) AutoReceiveMessage()

func (*PoisonPill) Descriptor deprecated

func (*PoisonPill) Descriptor() ([]byte, []int)

Deprecated: Use PoisonPill.ProtoReflect.Descriptor instead.

func (*PoisonPill) ProtoMessage

func (*PoisonPill) ProtoMessage()

func (*PoisonPill) ProtoReflect

func (x *PoisonPill) ProtoReflect() protoreflect.Message

func (*PoisonPill) Reset

func (x *PoisonPill) Reset()

func (*PoisonPill) String

func (x *PoisonPill) String() string

type Process

type Process interface {
	SendUserMessage(pid *PID, envelope *MessageEnvelope)
	SendSystemMessage(pid *PID, message SystemMessage)
	Stop(pid *PID)
}

A Process is an interface that defines the base contract for interaction of actors

type ProcessRegistry

type ProcessRegistry struct {
	SequenceID  uint64
	ActorSystem *ActorSystem
	Address     string
	LocalPIDs   *SliceMap
	// contains filtered or unexported fields
}

ProcessRegistry

@Description: 存储管理actor

func NewProcessRegistry

func NewProcessRegistry(actorSystem *ActorSystem) *ProcessRegistry

func (*ProcessRegistry) Add

func (pr *ProcessRegistry) Add(process Process, id string) (*PID, bool)

func (*ProcessRegistry) Get

func (pr *ProcessRegistry) Get(pid *PID) (Process, bool)

func (*ProcessRegistry) NextId

func (pr *ProcessRegistry) NextId() string

func (*ProcessRegistry) Remove

func (pr *ProcessRegistry) Remove(pid *PID)

type Producer

type Producer func() Actor

The Producer type is a function that creates a new actor

type ProducerWithActorSystem

type ProducerWithActorSystem func(system *ActorSystem) Actor

The ProducerWithActorSystem type is a function that creates a new actor

type Props

type Props struct {
	// contains filtered or unexported fields
}

func PropsFromFunc

func PropsFromFunc(f ReceiveFunc, opts ...PropsOption) *Props

PropsFromFunc creates a props with the given receive func assigned as the actor producer.

func PropsFromProducer

func PropsFromProducer(producer Producer, opts ...PropsOption) *Props

PropsFromProducer creates a props with the given actor producer assigned.

func (*Props) Configure

func (props *Props) Configure(opts ...PropsOption) *Props

type PropsOption

type PropsOption func(props *Props)

func WithFunc

func WithFunc(f ReceiveFunc) PropsOption

func WithMailbox

func WithMailbox(mailbox MailboxProducer) PropsOption

func WithProducer

func WithProducer(p Producer) PropsOption

func WithReceiverMiddleware

func WithReceiverMiddleware(middleware ...ReceiverMiddleware) PropsOption

func WithSenderMiddleware

func WithSenderMiddleware(middleware ...SenderMiddleware) PropsOption

func WithSpawnFunc

func WithSpawnFunc(spawn SpawnFunc) PropsOption

func WithSpawnMiddleware

func WithSpawnMiddleware(middleware ...SpawnMiddleware) PropsOption

type ReadonlyMessageHeader

type ReadonlyMessageHeader interface {
	Get(key string) string
	Keys() []string
	Length() int
	ToMap() map[string]string
}

type ReceiveFunc

type ReceiveFunc func(c Context)

The ReceiveFunc type is an adapter to allow the use of ordinary functions as actors to process messages

func (ReceiveFunc) Receive

func (f ReceiveFunc) Receive(c Context)

Receive calls f(c)

type ReceiveTimeout

type ReceiveTimeout struct{}

A ReceiveTimeout message is sent to an actor after the Context.ReceiveTimeout duration has expired

func (*ReceiveTimeout) SystemMessage

func (*ReceiveTimeout) SystemMessage()

type ReceiverContext

type ReceiverContext interface {
	// contains filtered or unexported methods
}

type ReceiverFunc

type ReceiverFunc func(c ReceiverContext, envelope *MessageEnvelope)

type ReceiverMiddleware

type ReceiverMiddleware func(next ReceiverFunc) ReceiverFunc

type Restart

type Restart struct{}

Restart is message sent by the actor system to control the lifecycle of an actor

func (*Restart) SystemMessage

func (*Restart) SystemMessage()

type Restarting

type Restarting struct{}

A Restarting message is sent to an actor when the actor is being restarted by the system due to a failure

func (*Restarting) AutoReceiveMessage

func (*Restarting) AutoReceiveMessage()

type ResumeMailbox

type ResumeMailbox struct{}

ResumeMailbox is message sent by the actor system to resume mailbox processing.

This will not be forwarded to the Receive method

func (*ResumeMailbox) SystemMessage

func (*ResumeMailbox) SystemMessage()

type RootContext

type RootContext struct {
	// contains filtered or unexported fields
}

func NewRootContext

func NewRootContext(actorSystem *ActorSystem, header map[string]string, middleware ...SenderMiddleware) *RootContext

func (*RootContext) Actor

func (rc *RootContext) Actor() Actor

func (*RootContext) ActorSystem

func (rc *RootContext) ActorSystem() *ActorSystem

func (*RootContext) Envelope

func (rc *RootContext) Envelope() *MessageEnvelope

func (*RootContext) Logger

func (rc *RootContext) Logger() *slog.Logger

func (*RootContext) MessageHeader

func (rc *RootContext) MessageHeader() ReadonlyMessageHeader

func (*RootContext) Parent

func (rc *RootContext) Parent() *PID

func (*RootContext) Poison

func (rc *RootContext) Poison(pid *PID)

func (*RootContext) PoisonFuture

func (rc *RootContext) PoisonFuture(pid *PID) *Future

PoisonFuture will tell actor to stop after processing current user messages in mailbox, and return its future.

func (*RootContext) Request

func (rc *RootContext) Request(pid *PID, envelope *MessageEnvelope) (*MessageEnvelope, error)

Request

@Description:
@receiver rc
@param pid
@param message message's type cannot be MessageEnvelope
@return *MessageEnvelope
@return error

func (*RootContext) Self

func (rc *RootContext) Self() *PID

func (*RootContext) Send

func (rc *RootContext) Send(pid *PID, envelope *MessageEnvelope)

func (*RootContext) Sender

func (rc *RootContext) Sender() *PID

func (*RootContext) Spawn

func (rc *RootContext) Spawn(props *Props) *PID

func (*RootContext) SpawnNamed

func (rc *RootContext) SpawnNamed(props *Props, name string) (*PID, error)

func (*RootContext) SpawnPrefix

func (rc *RootContext) SpawnPrefix(props *Props, prefix string) *PID

func (*RootContext) Stop

func (rc *RootContext) Stop(pid *PID)

func (*RootContext) StopFuture

func (rc *RootContext) StopFuture(pid *PID) *Future

StopFuture will stop actor immediately regardless of existing user messages in mailbox, and return its future.

func (*RootContext) WithHeaders

func (rc *RootContext) WithHeaders(headers map[string]string) *RootContext

func (*RootContext) WithSenderMiddleware

func (rc *RootContext) WithSenderMiddleware(middleware ...SenderMiddleware) *RootContext

func (*RootContext) WithSpawnMiddleware

func (rc *RootContext) WithSpawnMiddleware(middleware ...SpawnMiddleware) *RootContext

type SenderContext

type SenderContext interface {
	// contains filtered or unexported methods
}

type SenderFunc

type SenderFunc func(c SenderContext, target *PID, envelope *MessageEnvelope)

type SenderMiddleware

type SenderMiddleware func(next SenderFunc) SenderFunc

type SliceMap

type SliceMap struct {
	LocalPIDs []cmap.ConcurrentMap
}

func (*SliceMap) GetBucket

func (s *SliceMap) GetBucket(key string) cmap.ConcurrentMap

type SpawnFunc

type SpawnFunc func(actorSystem *ActorSystem, id string, props *Props, parentContext SpawnerContext) (*PID, error)
var DefaultSpawner SpawnFunc = defaultSpawner

DefaultSpawner this is a hacking way to allow Proto.Router access default spawner func.

type SpawnMiddleware

type SpawnMiddleware func(next SpawnFunc) SpawnFunc

type SpawnerContext

type SpawnerContext interface {
	// contains filtered or unexported methods
}

type Started

type Started struct{}

A Started message is sent to an actor once it has been started and ready to begin receiving messages.

func (*Started) SystemMessage

func (*Started) SystemMessage()

type Stop

type Stop struct {
	// contains filtered or unexported fields
}

func (*Stop) Descriptor deprecated

func (*Stop) Descriptor() ([]byte, []int)

Deprecated: Use Stop.ProtoReflect.Descriptor instead.

func (*Stop) ProtoMessage

func (*Stop) ProtoMessage()

func (*Stop) ProtoReflect

func (x *Stop) ProtoReflect() protoreflect.Message

func (*Stop) Reset

func (x *Stop) Reset()

func (*Stop) String

func (x *Stop) String() string

func (*Stop) SystemMessage

func (*Stop) SystemMessage()

type Stopped

type Stopped struct{}

A Stopped message is sent to the actor once it has been stopped. A stopped actor will receive no further messages

func (*Stopped) AutoReceiveMessage

func (*Stopped) AutoReceiveMessage()

type Stopping

type Stopping struct{}

A Stopping message is sent to an actor prior to the actor being stopped

func (*Stopping) AutoReceiveMessage

func (*Stopping) AutoReceiveMessage()

type Subscription

type Subscription struct {
	// contains filtered or unexported fields
}

Subscription is returned from the Subscribe function.

This value and can be passed to Unsubscribe when the observer is no longer interested in receiving messages

func (*Subscription) Activate

func (s *Subscription) Activate() bool

func (*Subscription) IsActive

func (s *Subscription) IsActive() bool

type SuspendMailbox

type SuspendMailbox struct{}

SuspendMailbox is message sent by the actor system to suspend mailbox processing.

This will not be forwarded to the Receive method

func (*SuspendMailbox) SystemMessage

func (*SuspendMailbox) SystemMessage()

type SystemMessage

type SystemMessage interface {
	SystemMessage()
}

A SystemMessage message is reserved for specific lifecycle messages used by the actor system

type Terminated

type Terminated struct {
	Who *PID             `protobuf:"bytes,1,opt,name=who,proto3" json:"who,omitempty"`
	Why TerminatedReason `protobuf:"varint,2,opt,name=Why,proto3,enum=actor.TerminatedReason" json:"Why,omitempty"`
	// contains filtered or unexported fields
}

func (*Terminated) Descriptor deprecated

func (*Terminated) Descriptor() ([]byte, []int)

Deprecated: Use Terminated.ProtoReflect.Descriptor instead.

func (*Terminated) GetWho

func (x *Terminated) GetWho() *PID

func (*Terminated) GetWhy

func (x *Terminated) GetWhy() TerminatedReason

func (*Terminated) ProtoMessage

func (*Terminated) ProtoMessage()

func (*Terminated) ProtoReflect

func (x *Terminated) ProtoReflect() protoreflect.Message

func (*Terminated) Reset

func (x *Terminated) Reset()

func (*Terminated) String

func (x *Terminated) String() string

func (*Terminated) SystemMessage

func (*Terminated) SystemMessage()

type TerminatedReason

type TerminatedReason int32
const (
	TerminatedReason_Stopped           TerminatedReason = 0
	TerminatedReason_AddressTerminated TerminatedReason = 1
	TerminatedReason_NotFound          TerminatedReason = 2
)

func (TerminatedReason) Descriptor

func (TerminatedReason) Enum

func (TerminatedReason) EnumDescriptor deprecated

func (TerminatedReason) EnumDescriptor() ([]byte, []int)

Deprecated: Use TerminatedReason.Descriptor instead.

func (TerminatedReason) Number

func (TerminatedReason) String

func (x TerminatedReason) String() string

func (TerminatedReason) Type

type Unwatch

type Unwatch struct {
	Watcher *PID `protobuf:"bytes,1,opt,name=Watcher,proto3" json:"Watcher,omitempty"`
	// contains filtered or unexported fields
}

func (*Unwatch) Descriptor deprecated

func (*Unwatch) Descriptor() ([]byte, []int)

Deprecated: Use Unwatch.ProtoReflect.Descriptor instead.

func (*Unwatch) GetWatcher

func (x *Unwatch) GetWatcher() *PID

func (*Unwatch) ProtoMessage

func (*Unwatch) ProtoMessage()

func (*Unwatch) ProtoReflect

func (x *Unwatch) ProtoReflect() protoreflect.Message

func (*Unwatch) Reset

func (x *Unwatch) Reset()

func (*Unwatch) String

func (x *Unwatch) String() string

func (*Unwatch) SystemMessage

func (*Unwatch) SystemMessage()

type Watch

type Watch struct {
	Watcher *PID `protobuf:"bytes,1,opt,name=Watcher,proto3" json:"Watcher,omitempty"`
	// contains filtered or unexported fields
}

system messages

func (*Watch) Descriptor deprecated

func (*Watch) Descriptor() ([]byte, []int)

Deprecated: Use Watch.ProtoReflect.Descriptor instead.

func (*Watch) GetWatcher

func (x *Watch) GetWatcher() *PID

func (*Watch) ProtoMessage

func (*Watch) ProtoMessage()

func (*Watch) ProtoReflect

func (x *Watch) ProtoReflect() protoreflect.Message

func (*Watch) Reset

func (x *Watch) Reset()

func (*Watch) String

func (x *Watch) String() string

func (*Watch) SystemMessage

func (*Watch) SystemMessage()

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL