Coder Social home page Coder Social logo

exactor's People

Contributors

aaronjensen avatar amclain avatar d0rc avatar edgurgel avatar kaysackey avatar liveforeverx avatar mazyod avatar parroty avatar sairam avatar sasa1977 avatar waialualib avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

exactor's Issues

DSL for :local, :global name registration from supervisor's spec

In Elixir we usually have:

  def init([]) do
    children = [
     worker(SomeWorker, [])
    ]
    supervise(children, strategy: :one_for_one)
  end

It could very handy to have be able to add named ExActors like this:

children = [  worker(ExActoredServer, [args_for_server, [name: [local: MyFirstServer]]]) ]

Or to have some similar (in sense of expressiveness) syntax / DSL.

NB: There is one more issue - registering :global name - in clustered setup ExActor may fail to start because of name conflict. So, I guess, some way to fallback to "slave" mode may be required. Like, for example, here:

https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/topic/server.ex#L17

Generate typespecs as well

How would you feel about adding support for typespecs?

  defcast inc(x :: integer), state: state, do: new_state(state + x)

would generate

@spec inc(x :: integer)
  def inc(pid, x), do: GenServer.cast(pid, {:inc, x})

Support for Elixir 1.5 @impl

It doesn't appear that there's a way to use the @impl directive with ExActor.

In a GenServer using ExActor, I have a terminate() function. If I use the @impl directive on it, I'm warned about not having the directive on the macro-generated call backs in the GenServer.

`export:` only accept atom.

I wish it could be used like export: @name or export: __MODULE__.

But it gives:

** (CaseClauseError) no case clause matching: {:__MODULE__, [line: 16], nil}
    lib/exactor/operations.ex:644: ExActor.Operations.server_ref/2
    lib/exactor/operations.ex:632: ExActor.Operations.gen_server_args/3
    lib/exactor/operations.ex:572: ExActor.Operations.define_interface/5
    lib/exactor/operations.ex:483: ExActor.Operations.def_request/3
    lib/core/player_manager.ex:16: (module)

function undefined error at elixir v0.11.0

Hi. I'm playing around elixir v0.11.0, and facing the following error. The current mix.exs is limited as "~> 0.10.3", but is there're any plan for supporting v0.11.0?
(I was trying to avoid the error, but couldn't make it work, and looking for your insight).

tmp/github/exactor[master*]% mix test

** (CompileError) test/exactor_test.exs:7: function exported/0 undefined
    src/elixir_translator.erl:573: :elixir_translator.translate_arg/2
    lists.erl:1339: :lists.mapfoldl/3
    src/elixir_translator.erl:580: :elixir_translator.translate_args/2
    src/elixir_translator.erl:610: :elixir_translator.translate_apply/7
    src/elixir_translator.erl:573: :elixir_translator.translate_arg/2
    lists.erl:1339: :lists.mapfoldl/3
    lists.erl:1340: :lists.mapfoldl/3
    test/exactor_test.exs:7: ExActor.Test.TestActor (module)

I'm assuming the error is caused by the following change.

https://github.com/elixir-lang/elixir/releases/tag/v0.11.0

[Kernel] Quoted variables from the same module must be explicitly shared. Previously, if a function returned quote do: a = 1, another function from the same module could access it as quote do: a. This has been fixed and the variables must be explicitly shared with var!(a, MODULE)

Applying the "var!" for "exported" variable in the quote block removed the above error, but "(CompileError) test/exactor_test.exs:7: function pid/0 undefined" followed. I couldn't identify the how the pid variable is being passed around.

Struct pattern matching error

Hello Saša, and thanks for making the 2.2.1 release!

I just had the time to try and upgrade my project and test the dependencies, and my ExActor GenServer is failing to properly pattern match against a struct.

Please consider the following code:

defcall process(%Socks.Game{} = game) do
  IO.inspect game
  ...
end

Of course, the %Socks.Game{} is just used for pattern matching, however, when I hit the IO.inspect, the printed game is an empty Socks.Game struct, even though I've passed in a filled Socks.Game object.

I caught this during unit tests, so I cleaned the dependencies, installed v2.2.0, and everything worked again. Cleaned the dependencies again, installed v2.2.1, and the test broke again. That's to say, I'm pretty confident something slipped through the cracks in the v2.2.1 release.

stop_server not usable from within defstart

The stop_server command is not usable from within defstart, seemingly because the :state_var is not set for it, yet you are able to return a {:stop, blah...} tuple from the init function to prevent GenServer load.

defcall can not use in quote

code like below can not work since i want to inject code from other module for grouping
quote do
defcall get_any do
reply :ok
end
end
but using get_any() it works

Can't build docs for project what uses exactor

My project uses exactor. When I do mix docs, the command returns without an error. No documentation is created. mix help does not show mix docs as an option.

If I comment out the contexts of file
project_root/deps/exactor/lib/mix/tasks/docs.ex I can build the docs for my project.

Here is the contexts of my mix.exs file:

defmodule DocTest.Mixfile do
use Mix.Project

def project do
[app: :doc_test,
version: "0.0.1",
elixir: "> 0.13.1",
deps: deps]
end
def application do
[ applications: [],
mod: {DocTest, []} ]
end
defp deps do
[
{:exactor, "
>0.3.2"},
{ :ex_doc, github: "elixir-lang/ex_doc" }
]
end
end

Possibility of custom process registration dispatching logic?

Right now, it is possible to either return a PID, or to register using :global or :via. However, this needs to be given as option when ExActor.GenServer is included (used).

This unfortunately which means that it is impossible to build custom logic, to e.g. register at {:via, Registry, {MyRegistry, "user_#{user_id}"}}.

Maybe, a possibility would be to allow users to write a custom export function, which is used for the different functions to transform the first argument into a term like above that could be used to do the actual GenServer dispatching on.

Testing support

I have a question about ExActor and how to support testing.

Here's a bit of an intro: after some toy services and problems ("toy" as in "relatively simple" - we do run some of this in production) I'm cutting my teeth on some things that are more complex, especially in how multiple modules/processes/... interact, to help guide my thinking of how to transfer all my knowledge and gut feelings from mostly the OO world (I'm a Smalltalker at heart, still 😉) to the Erlang model. To make a long story short, I have the feeling that with some minimal adjustments to a library like ExActor we could have a nice way of testing inter-process (well, inter-genserver) interactions without breaking encapsulation, etcetera. I have been jotting down my thoughts https://github.com/cdegroot/simpler/blob/master/notes.org mostly to help me structure my own thinking. To make a long story short, if we could change one thing in ExActor and add one thing, then it'd not only be a cool library to write shorthand GenServers, but also to actively support nicer testing approaches than what I'm seeing in the wild. Specifically, i'd like the message format to be exposed (through helper functions) so you could pattern match on it in tests. Quoting myself from my notes, I'd like to write:

test "foo" do
  # ... do some testing ...
  expect_called Person.print(self())
end

where expect_called would expand in an assert_received with the argument being converted in the message being created by print's defcall or defcast (where you probably want to have an expect_call for a cast). This way, it's possible to write down intent and not break encapsulation by keeping the message format that ExActor uses under wraps. For more precise matching, but I'm not sure whether that's needed or not, it'd be neat if ExActor sends the module along in its internal message format so some more convoluted test could say something like

expect_called Person.print
expect_called SomethingElse.print

Does that all make sense? Would you be willing to accept a PR that would add this to ExActor? (If I can figure out the code - macros in Elixir not yet my strongest point ;-)).

Pass timeout parameter

Hi Saša,

Thank you for this great library! I'm using it in multiple projects already.

What's the best way to pass a user-defined timeout parameter if the call is not made from another ExActor (where I could use timeout_after(:timer.seconds(10))), but from somewhere else?

Currently I have to fall back to the original GenServer implementation of Elixir and cannot use the ExActor API when making a call with a custom timeout. Example:

{:ok, pid} = CSVImporter.start_link
GenServer.call(pid, {:import, path}, :infinity)

What I would prefer is something like this:

{:ok, pid} = CSVImporter.start_link
CSVImporter.import(pid, path, :infinity)

The last parameter is currently not handled as a separate timeout parameter, but translated to CSVImporter.import(pid, path, :infinity) which is not what I want. Is there a way to make timeout calls using the ExActor API?

Thanks,
Florian

Unused variable warnings when variables created in map pattern match

I have some function headers like so:

defcall set_open_device(%{"path" => path, "baud" => speed}), state: state do

"path" and "speed" are used in the function, but I see the following compiler warnings:

warning: variable "path" is unused
  lib/rni/dispatch/fmt.ex:53

warning: variable "speed" is unused
  lib/rni/dispatch/fmt.ex:53

Can this be used with a via_tuple?

I am using Elixir's Registry (though I don't think this matters) to keep track of multiple processes born from the same module all with a different id. I'm not sure I can do this cleanly with this package. Is that true, or am I missing the option that allows it? All I saw was use ExActor.GenServer, export: {:global, :global_registered_name} but it doesn't look like it will work if I need to spawn two of this kind of process and give them different names?

Why was ExActor not a good idea?

From the README.md:

I don't maintain this project anymore. In hindsight, I don't think it was a good idea in the first place. I haven't been using ExActor myself for years, and I recommend sticking with regular GenServer instead :-)

Can you expand on why ExActor wasn't a good idea? On the surface of it, removing boilerplate and standardising the APIs to gen_servers sounds good.

Elixir > 1.2 throws compile-time warnings for unused variables

In Elixir >= 1.2.3, compile-time warnings are generated that tell that the variables in one of the defcall, defstart, etc. definitions are unused.

This is obviously not true, but it would be nice if the code could be restructured so the warnings would not be generated at all, as it becomes easy to miss other warnings that have to be acted upon.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.