{"id":27966464,"url":"https://github.com/techery/swactors","last_synced_at":"2025-05-07T20:18:55.976Z","repository":{"id":35615537,"uuid":"39889172","full_name":"techery/Swactors","owner":"techery","description":"Swactors","archived":false,"fork":false,"pushed_at":"2015-08-20T13:37:02.000Z","size":692,"stargazers_count":1,"open_issues_count":1,"forks_count":2,"subscribers_count":40,"default_branch":"master","last_synced_at":"2025-05-07T20:18:51.723Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/techery.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-29T11:07:44.000Z","updated_at":"2016-09-05T04:01:22.000Z","dependencies_parsed_at":"2022-09-16T21:21:26.383Z","dependency_job_id":null,"html_url":"https://github.com/techery/Swactors","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techery%2FSwactors","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techery%2FSwactors/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techery%2FSwactors/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/techery%2FSwactors/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/techery","download_url":"https://codeload.github.com/techery/Swactors/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252949223,"owners_count":21830154,"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":[],"created_at":"2025-05-07T20:18:55.427Z","updated_at":"2025-05-07T20:18:55.968Z","avatar_url":"https://github.com/techery.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Swactors\n\nThe actor model in computer science is a mathematical model of concurrent computation that treats \"actors\" as the universal primitives of concurrent computation: in response to a message that it receives, an actor can make local decisions, create more actors, send more messages, and determine how to respond to the next message received. [(Wikipedia)](https://en.wikipedia.org/wiki/Actor_model).\n\nIn actor model we have complete set of actor objects, where every actor implements it's own behavior. In order to execute it's behavior actor should receive a message of a certain type.\nActor define set of messages that he can accept and reactions for them. Messages are sent asynchronously, but actor is processing them one at time, while other messages are waiting for their turn in a queue.\n\n##Actors and messages##\n\nTo create an actor you have to inherit from DTActor class:\n```\n@interface DTSessionActor : DTActor\n@end\n```\nThen override `-setup:`, define what kind of messeges actor can accept and provide reactions for them:\n```\n- (void)setup {\n    [self on:[DTLogin class] doFuture:^RXPromise *(DTLogin *message) {\n        return [self askSession:message.email password:message.password];\n    }];\n\n    [self on:[DTLogout class] _do:^(id o) {\n        [self.sessionStorage clear];\n    }];\n}\n```\nThere 3 types of reactions to message: \n- **void** - just do work, return nothing;\n- **result** - return result immediately;\n- **future** - return future object - useful for async tasks, or then message is redirected to another actor.\n\n##Actor System##\n\nActor usually have references to other actors and communicates with them also through message-passing mechanism.\nActors initialize inside actor system and reference to them can only be obtained through system.\n\nHow to create actor system:\n```\nDTMainActorSystem *system = [[DTMainActorSystem alloc] initWithConfigs:configs serviceLocator:serviceLocator builderBlock:^(DTActorSystemBuilder * builder) {\n    [builder addActorsPull:[DTAPIActor class] count:3];\n    [builder addSingleton:[DTSessionActor class]];\n    [builder addActor:^DTActor *(id\u003cDTActorSystem\u003e system) {\n        return [DTAuthActor actorWithActorSystem:system];\n    }];\n}];\n```\nTypes of actor providers that could be added to system:\n\n- **Singleton** - an actor of provided class would be created on first access;\n- **Instance** - already inialized actor, could be useful if you need custom initialization;\n- **Actors Pull** - as was said before, every actor could handle only one message at a time, which sometime is not useful. For netwrok for example needed possibility to proccess few messages simultaniously. On sending messages to actors pull system eather take first free actor, or creates new if pull isn't filled yet, or if all actors are busy it just takes any actor from the pull.\n\n##Sending message##\n\nTo send message to actor you need actor reference:\n```\nDTActorRef *sessionActor = [sut actorOfClass:[NSObject class] caller:self];\n```\nMessage of any class could be sent to actor (but it's preffered for message to be immutable):\n```\nRXPromise *session = [sessionActor ask:[[DTLogin alloc] initWithLogin:login password:password]];\n```\n\nResult of message sending is Future object which will be fulfilled with some result or rejected with error:\n```\nsession.then(^id(id result){\n    NSLog(@\"Session: %@\", result);\n    return nil;\n}, \n^id(NSError* error){\n    NSLog(@\"Error: %@\", error);\n    return nil;\n});\n```\n\n##ServiceLocator ##\n\nActor system is initizlized with ServiceLocator. ServiceLocator is an object that contains references to your custom services that are not actors.\nYou can register you services by class or protocol:\n```\nDTServiceLocator *serviceLocator = [[DTServiceLocator alloc] initWithBuilderBlock:^(DTServiceLocator *locator) {\n    DTSessionStorage *sessionStorage = [DTSessionStorage new];\n    [serviceLocator registerService:sessionStorage];\n    [serviceLocator registerService:[DTSessionStorage new] forProtocol:@protocol(DTSessionProvider)];\n}];\n```\nAnd later get access to them in your actor:\n```\n[self on:[DTLogout class] _do:^(id o) {\n    DTSessionStorage *sessionStorage = [self.serviceLocator serviceForClass:[DTSessionStorage class]];\n    [sessionStorage clear];\n}];\n```\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechery%2Fswactors","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftechery%2Fswactors","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftechery%2Fswactors/lists"}