#actor that sends a message to itself after some time

1 messages · Page 1 of 1 (latest)

patent willow
#

Hello I'm trying to write an actor that polls github api to include in my app supervision tree.
The responses have a header telling me after how many seconds I can make a new request.
So in my mind it would work somehow like this:

fn notification_actor() {
  actor.on_message(actor.new(Nil), fn(state, message) {
    case message {
      PollIntervalExpired -> {
        let assert Ok(response) = todo as "the request"
        let sleep_seconds =
          list.key_find(response.headers, "x-poll-interval")
          |> result.try(int.parse)
          |> result.unwrap(60)

        todo as "parse the response body"

        // And now I'm not sure what to do...
        // Here I was thinking of sending a message to myself
        // after the given amount of seconds.
        // 
        // I couldn't find an easy way to find a reference
        // to self that I could send a message to
        //
        // But I'm getting a feeling this might not be how
        // actors are meant to be used
        actor.continue(Nil)
      }
    }
  })
}

How should I go about this?

drowsy star
#

You could store a reference to self in state on init, then use process.send_after

patent willow
#

Oh! I should have checked new_with_initialiser

atomic totem
#

oh no jak is doing otp

#

we're doomed

patent willow
#

Well since we're here

#

If an actor in a static supervision tree fails during initialisation, will the supervisor try and restart it, or will it give up?

atomic totem
#

you could also just test it!

final garden
#

what Isaac said + if your initializer is set up so that your start function returns the actor's Subject(Message), you can just immediately send a message to it after calling actor.start to kick things off

upbeat cliff
#

Restarting begins after application initialisation finishes

#

Initialisation is the chance you have for detecting total failure and aborting the whole program

patent willow
#

Hayleigh spreading fake news

#

That’s good to know, thanks!

atomic totem
#

noooooo

#

i knew it 😂

#

louis was away so wasnt around to correct me

mystic lion
# upbeat cliff It fails

this may be a silly question; but:
is this the same for factory supervisors? or just static ones

upbeat cliff
#

Not just supervisors

#

Its a feature of OTP generally

mystic lion
#

so web requests, to services that might temporarily be unreachable, should be handled outside of the initializer

in my case its getting a list of roles for a specific discord/fluxer guild(community) before starting an actor that takes care of that specific guild

ig the way to go would then be to try to get the roles beforehand
and then either starting immediately or returning with a failure and trying again later livThink

upbeat cliff
#

Process initialisers will run both during app initialisation and afterwards

mystic lion
#

i just realized what i was about to ask was quite silly derpeline

its fine to have that in the initialiser of a factory since factory.start_child returns a result that i can then handle accordingly; right?

i.e. doing

factory.get_by_name(factory_name)
|> factory.start_child(StartGuildActor(state.client, guild_id))

with this kind of setup

pub fn supervised(
  guild_factory: process.Name(_),
  manager_name: process.Name(_),
  client: grom.Client,
  bot_user: user.User,
) -> supervision.ChildSpecification(static_supervisor.Supervisor) {
  static_supervisor.new(static_supervisor.RestForOne)
  |> static_supervisor.add(factory(guild_factory))
  |> static_supervisor.add(manager(..))
  |> static_supervisor.supervised()
}

fn factory(guild_factory: process.Name(_)) -> supervision.ChildSpecification(_) {
  factory.worker_child(guild_actor)
  |> factory.named(guild_factory)
  |> factory.supervised()
}

fn guild_actor(
  args: StartGuildActor,
) {
 actor.new_with_initialiser(5000, fn(subj) {
    let GuildId(guild_id) = args.guild_id
    use roles <- result.try(
      guild.get_roles(args.client, guild_id)
      |> result.map_error(string.inspect),
    )

    actor.initialised(GuildActorState(guild_id: args.guild_id, roles:))
    |> actor.returning(subj)
    |> Ok
  })
  |> actor.on_message(on_guild_message)
  |> actor.start()
}
upbeat cliff
#

potentially aye

mystic lion
#

im just gonna experiment with otp stuff n see what happens