{"id":14333146,"url":"https://github.com/anthdm/hollywood","last_synced_at":"2025-05-14T04:07:33.692Z","repository":{"id":65536822,"uuid":"594072416","full_name":"anthdm/hollywood","owner":"anthdm","description":"Blazingly fast and light-weight Actor engine written in Golang","archived":false,"fork":false,"pushed_at":"2025-03-28T07:13:10.000Z","size":420,"stargazers_count":1846,"open_issues_count":20,"forks_count":131,"subscribers_count":32,"default_branch":"master","last_synced_at":"2025-04-12T05:59:42.181Z","etag":null,"topics":["actor-model","distributed-systems","fault-tolerance","golang","microservices"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/anthdm.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-27T14:36:30.000Z","updated_at":"2025-04-11T22:56:42.000Z","dependencies_parsed_at":"2023-12-11T16:27:34.710Z","dependency_job_id":"b45e954e-e8ea-4863-9385-d1a52c590dde","html_url":"https://github.com/anthdm/hollywood","commit_stats":{"total_commits":178,"total_committers":14,"mean_commits":"12.714285714285714","dds":0.3033707865168539,"last_synced_commit":"9721d9cf9fc38248767870d826e8ec9e9662d892"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthdm%2Fhollywood","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthdm%2Fhollywood/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthdm%2Fhollywood/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/anthdm%2Fhollywood/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/anthdm","download_url":"https://codeload.github.com/anthdm/hollywood/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254069216,"owners_count":22009511,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actor-model","distributed-systems","fault-tolerance","golang","microservices"],"created_at":"2024-08-25T18:00:42.766Z","updated_at":"2025-05-14T04:07:33.668Z","avatar_url":"https://github.com/anthdm.png","language":"Go","readme":"[![Go Report Card](https://goreportcard.com/badge/github.com/anthdm/hollywood)](https://goreportcard.com/report/github.com/anthdm/hollywood)\n![example workflow](https://github.com/anthdm/hollywood/actions/workflows/build.yml/badge.svg?branch=master)\n\u003ca href=\"https://discord.gg/gdwXmXYNTh\"\u003e\n\t\u003cimg src=\"https://discordapp.com/api/guilds/1025692014903316490/widget.png?style=shield\" alt=\"Discord Shield\"/\u003e\n\u003c/a\u003e\n\n# Blazingly fast, low latency actors for Golang\n\nHollywood is an ULTRA fast actor engine build for speed and low-latency applications. Think about game servers,\nadvertising brokers, trading engines, etc... It can handle **10 million messages in under 1 second**.\n\n## What is the actor model?\n\nThe Actor Model is a computational model used to build highly concurrent and distributed systems. It was introduced by\nCarl Hewitt in 1973 as a way to handle complex systems in a more scalable and fault-tolerant manner.\n\nIn the Actor Model, the basic building block is an actor, sometimes referred to as a receiver in Hollywood, \nwhich is an independent unit of computation that communicates with other actors by exchanging messages. \nEach actor has its own state and behavior, and\ncan only communicate with other actors by sending messages. This message-passing paradigm allows for a highly\ndecentralized and fault-tolerant system, as actors can continue to operate independently even if other actors fail or\nbecome unavailable.\n\nActors can be organized into hierarchies, with higher-level actors supervising and coordinating lower-level actors. This\nallows for the creation of complex systems that can handle failures and errors in a graceful and predictable way.\n\nBy using the Actor Model in your application, you can build highly scalable and fault-tolerant systems that can handle a\nlarge number of concurrent users and complex interactions.\n\n## Features\n\nCompiles to WASM! Both GOOS=js and GOOS=wasm32\n\n- Guaranteed message delivery on actor failure (buffer mechanism)\n- Fire \u0026 forget or request \u0026 response messaging, or both\n- High performance dRPC as the transport layer\n- Optimized proto buffers without reflection\n- Lightweight and highly customizable\n- Cluster support for writing distributed self discovering actors \n\n# Benchmarks\n\n```\nmake bench\n```\n\n```\nspawned 10 engines\nspawned 2000 actors per engine\nSend storm starting, will send for 10s using 20 workers\nMessages sent per second 3244217\n..\nMessages sent per second 3387478\nConcurrent senders: 20 messages sent 35116641, messages received 35116641 - duration: 10s\nmessages per second: 3511664\ndeadletters: 0\n```\n\n# Installation\n\n```\ngo get github.com/anthdm/hollywood/...\n```\n\n\u003e Hollywood requires Golang version `1.21`\n\n# Quickstart\n\nWe recommend you start out by writing a few examples that run locally. Running locally is a bit simpler as the compiler\nis able to figure out the types used. When running remotely, you'll need to provide protobuffer definitions for the\ncompiler.\n\n## Hello world.\n\nLet's go through a Hello world message. The complete example is available in the \n[hello world](examples/helloworld) folder. Let's start in main:\n```go\nengine, err := actor.NewEngine(actor.NewEngineConfig())\n```\nThis creates a new engine. The engine is the core of Hollywood. It's responsible for spawning actors, sending messages\nand handling the lifecycle of actors. If Hollywood fails to create the engine it'll return an error. For development \nyou shouldn't use to pass any options to the engine so you can pass nil. We'll look at the options later.\n\nNext we'll need to create an actor. These are some times referred to as `Receivers` after the interface they must \nimplement. Let's create a new actor that will print a message when it receives a message. \n\n```go\npid := engine.Spawn(newHelloer, \"hello\")\n```\nThis will cause the engine to spawn an actor with the ID \"hello\". The actor will be created by the provided \nfunction `newHelloer`. Ids must be unique. It will return a pointer to a PID. A PID is a process identifier. It's a unique identifier for the actor. Most of\nthe time you'll use the PID to send messages to the actor. Against remote systems you'll use the ID to send messages, \nbut on local systems you'll mostly use the PID.\n\nLet's look at the `newHelloer` function and the actor it returns. \n\n```go\ntype helloer struct{}\n\nfunc newHelloer() actor.Receiver {\n\treturn \u0026helloer{}\n}\n```\n\nSimple enough. The `newHelloer` function returns a new actor. The actor is a struct that implements the actor.Receiver.\nLets look at the `Receive` method.\n\n```go\ntype message struct {\n\tdata string\n}\n\nfunc (h *helloer) Receive(ctx *actor.Context) {\n\tswitch msg := ctx.Message().(type) {\n\tcase actor.Initialized:\n\t\tfmt.Println(\"helloer has initialized\")\n\tcase actor.Started:\n\t\tfmt.Println(\"helloer has started\")\n\tcase actor.Stopped:\n\t\tfmt.Println(\"helloer has stopped\")\n\tcase *message:\n\t\tfmt.Println(\"hello world\", msg.data)\n\t}\n}\n```\n\nYou can see we define a message struct. This is the message we'll send to the actor later. The Receive method\nalso handles a few other messages. These lifecycle messages are sent by the engine to the actor, you'll use these to \ninitialize your actor\n\nThe engine passes an actor.Context to the `Receive` method. This context contains the message, the PID of the sender and\nsome other dependencies that you can use.\n\nNow, lets send a message to the actor. We'll send a `message`, but you can send any type of message you want. The only\nrequirement is that the actor must be able to handle the message. For messages to be able to cross the wire \nthey must be serializable. For protobuf to be able to serialize the message it must be a pointer. \nLocal messages can be of any type.\n\nFinally, lets send a message to the actor.\n\n```go\nengine.Send(pid, \u0026message{data: \"hello, world!\"})\n```\n\nThis will send a message to the actor. Hollywood will route the message to the correct actor. The actor will then print\na message to the console.\n\nThe **[examples](examples/)** folder is the best place to learn and\nexplore Hollywood further.\n\n\n## Spawning actors\n\nWhen you spawn an actor you'll need to provide a function that returns a new actor. As the actor is spawn there are a few\ntunable options you can provide.\n\n### With default configuration\n```go\ne.Spawn(newFoo, \"myactorname\")\n```\n\n### Passing arguments to the constructor\n\nSometimes you'll want to pass arguments to the actor constructor. This can be done by using a closure. There is\nan example of this in the [request example](examples/request). Let's look at the code.\n\nThe default constructor will look something like this:\n```go\nfunc newNameResponder() actor.Receiver {\n\treturn \u0026nameResponder{name: \"noname\"}\n}\n```\n\nTo build a new actor with a name you can do the following:\n```go\nfunc newCustomNameResponder(name string) actor.Producer {\n\treturn func() actor.Receiver {\n\t\treturn \u0026nameResponder{name}\n\t}\n}\n\n```\nYou can then spawn the actor with the following code:\n```go\npid := engine.Spawn(newCustomNameResponder(\"anthony\"), \"name-responder\")\n```\n\n### With custom configuration\n```go\ne.Spawn(newFoo, \"myactorname\",\n\tactor.WithMaxRestarts(4),\n\t\tactor.WithInboxSize(1024 * 2),\n\t\tactor.WithId(\"bar\"),\n\t)\n)\n```\nThe options should be pretty self explanatory. You can set the maximum number of restarts, which tells the engine\nhow many times the given actor should be restarted in case of panic, the size of the inbox, which sets a limit on how\nand unprocessed messages the inbox can hold before it will start to block.\n\n### As a stateless function \nActors without state can be spawned as a function, because its quick and simple.\n```go\ne.SpawnFunc(func(c *actor.Context) {\n\tswitch msg := c.Message().(type) {\n\tcase actor.Started:\n\t\tfmt.Println(\"started\")\n\t\t_ = msg\n\t}\n}, \"foo\")\n```\n\n## Remote actors\nActors can communicate with each other over the network with the Remote package. \nThis works the same as local actors but \"over the wire\". Hollywood supports serialization with protobuf.\n\n### Configuration\n\nremote.New() takes a listen address and a remote.Config struct.\n\nYou'll instantiate a new remote with the following code:\n```go\ntlsConfig := TlsConfig: \u0026tls.Config{\n\tCertificates: []tls.Certificate{cert},\n}\n\nconfig := remote.NewConfig().WithTLS(tlsConfig)\nremote := remote.New(\"0.0.0.0:2222\", config)\n\nengine, err := actor.NewEngine(actor.NewEngineConfig().WithRemote(remote))\n```\n\nLook at the [Remote actor examples](examples/remote) and the [Chat client \u0026 Server](examples/chat) for more information.\n\n## Eventstream\n\nIn a production system thing will eventually go wrong. Actors will crash, machines will fail, messages will end up in\nthe deadletter queue. You can build software that can handle these events in a graceful and predictable way by using\nthe event stream.\n\nThe Eventstream is a powerful abstraction that allows you to build flexible and pluggable systems without dependencies. \n\n1. Subscribe any actor to a various list of system events\n2. Broadcast your custom events to all subscribers \n\nNote that events that are not handled by any actor will be dropped. You should have an actor subscribed to the event \nstream in order to receive events. As a bare minimum, you'll want  to handle `DeadLetterEvent`. If Hollywood fails to \ndeliver a message to an actor it will send a `DeadLetterEvent` to the event stream. \n\nAny event that fulfills the `actor.LogEvent` interface will be logged to the default logger, with the severity level, \nmessage and the attributes of the event set by the `actor.LogEvent` `log()` method.\n\n### List of internal system events \n* `actor.ActorInitializedEvent`, an actor has been initialized but did not processed its `actor.Started message`\n* `actor.ActorStartedEvent`, an actor has started\n* `actor.ActorStoppedEvent`, an actor has stopped\n* `actor.DeadLetterEvent`, a message was not delivered to an actor\n* `actor.ActorRestartedEvent`, an actor has restarted after a crash/panic.\n* `actor.RemoteUnreachableEvent`, sending a message over the wire to a remote that is not reachable.\n* `cluster.MemberJoinEvent`, a new member joins the cluster \n* `cluster.MemberLeaveEvent`, a new member left the cluster \n* `cluster.ActivationEvent`, a new actor is activated on the cluster \n* `cluster.DeactivationEvent`, an actor is deactivated on the cluster \n\n### Eventstream example\n\nThere is a [eventstream monitoring example](examples/eventstream-monitor) which shows you how to use the event stream.\nIt features two actors, one is unstable and will crash every second. The other actor is subscribed to the event stream\nand maintains a few counters for different events such as crashes, etc. \n\nThe application will run for a few seconds and the poison the unstable actor. It'll then query the monitor with a \nrequest. As actors are floating around inside the engine, this is the way you interact with them. main will then print\nthe result of the query and the application will exit.\n\n## Customizing the Engine\n\nWe're using the function option pattern. All function options are in the actor package and start their name with\n\"EngineOpt\". Currently, the only option is to provide a remote. This is done by\n\n```go\nr := remote.New(remote.Config{ListenAddr: addr})\nengine, err := actor.NewEngine(actor.EngineOptRemote(r))\n```\naddr is a string with the format \"host:port\".\n\n## Middleware\n\nYou can add custom middleware to your Receivers. This can be useful for storing metrics, saving and loading data for\nyour Receivers on `actor.Started` and `actor.Stopped`.\n\nFor examples on how to implement custom middleware, check out the middleware folder in the ***[examples](examples/middleware)***\n\n## Logging\n\nHollywood has some built in logging. It will use the default logger from the `log/slog` package. You can configure the\nlogger to your liking by setting the default logger using `slog.SetDefaultLogger()`. This will allow you to customize \nthe log level, format and output. Please see the `slog` package for more information.\n\nNote that some events might be logged to the default logger, such as `DeadLetterEvent` and `ActorStartedEvent` as these\nevents fulfill the `actor.LogEvent` interface. See the Eventstream section above for more information.\n\n# Test\n\n```\nmake test\n```\n\n# Community and discussions\nJoin our Discord community with over 2000 members for questions and a nice chat.\n\u003cbr\u003e\n\u003ca href=\"https://discord.gg/gdwXmXYNTh\"\u003e\n\t\u003cimg src=\"https://discordapp.com/api/guilds/1025692014903316490/widget.png?style=banner2\" alt=\"Discord Banner\"/\u003e\n\u003c/a\u003e\n\n# Used in Production By\n\nThis project is currently used in production by the following organizations/projects:\n\n- [Sensora IoT](https://sensora.io)\n- [Market Monkey Terminal](https://marketmonkeyterminal.com)\n\n# License\n\nHollywood is licensed under the MIT licence.\n","funding_links":[],"categories":["Actor Model","Go"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanthdm%2Fhollywood","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fanthdm%2Fhollywood","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fanthdm%2Fhollywood/lists"}