erlangwebmachine

How would I start more than one instance of webmachine in an erlang application?


I'm trying to create two instances of webmachine in one erlang application. Each instance is to run on a different port and has its own specific configuration. Following the webmachine doc here, I have added the following processes to be started in my supervisor spec (application_sup.erl):

 {
    webmachine_instance_1,
    { webmachine_mochiweb, start, 
       [
          [
              { ip, "0.0.0.0"},
              { port, 8000},
              { dispatch, [ {["*"], file_resource, []} ] }
          ] 
        ]
    },
    permanent,
    5000,
    worker,
    dynamic
 },
 {
    webmachine_instance_2,
    { webmachine_mochiweb, start, 
       [
          [
              { ip, "0.0.0.0"},
              { port, 8080},
              { dispatch, [ {["*"], file_resource, []} ] }
          ] 
       ]
    },
    permanent,
    5000,
    worker,
    dynamic
 }

When I include both instances, I get a start error and cannot start my erlang application. After just trying to run the application with a single instance of webmachine (webmachine_instance_1 OR webmachine_instance_2), my application starts up fine.

Here is the specific error:

=PROGRESS REPORT==== 11-Mar-2014::17:00:31 ===
      supervisor: {local, application_sup}
         started: [{pid,<0.230.0>},
                   {name,webmachine_instance_1},
                   {mfargs,
                       {webmachine_mochiweb,start,
                           [[{ip,"0.0.0.0"},
                             {port,8000},
                             {dispatch, [{['*'],
                                   file_resource,
                                   []
                             }]}]
                            ]
                        }
                   },
                   {restart_type,permanent},
                   {shutdown,5000},
                   {child_type,worker}] 

 =SUPERVISOR REPORT==== 11-Mar-2014::17:00:31 ===
     Supervisor: {local, application_sup}
     Context:    start_error
     Reason:     {'EXIT',
                 {undef,
                     [{webmachine_mochiweb,start,
                          [{ip,"0.0.0.0"},
                           {port,8080},
                           {dispatch,[{["*"],file_resource,[]}]}],
                          []},
                      {supervisor,do_start_child,2,
                          [{file,"supervisor.erl"},{line,303}]},
                      {supervisor,start_children,3,
                          [{file,"supervisor.erl"},{line,287}]},
                      {supervisor,init_children,2,
                          [{file,"supervisor.erl"},{line,253}]},
                      {gen_server,init_it,6,
                          [{file,"gen_server.erl"},{line,304}]},
                      {proc_lib,init_p_do_apply,3,
                          [{file,"proc_lib.erl"},{line,227}]}]}}
 Offender:   [{pid,undefined},
              {name,webmachine_instance_2},
              {mfargs,
                  {webmachine_mochiweb,start,
                      [{ip,"0.0.0.0"},
                       {port,8080},
                       {dispatch,[{["*"],file_resource,[]}]}]}},
              {restart_type,permanent},
              {shutdown,5000},
              {child_type,worker}]

I am fairly new to erlang and might not quite understand the underlying issues here - according to the webmachine doc we should be able to start two instances of the same application but with different configurations in an erlang app.

Thanks for any help/discussion on this issue!


Solution

  • Your child process config should have the following form:

    {Name,
     {webmachine_mochiweb, start, [WebConfig]},
      permanent, 5000, worker, [mochiweb_socket_server]}
    

    where Name and WebConfig must be unique to your webmachine instance. The WebConfig part should include name and dispatch_group properties. For example:

    WebConfig = [{name,instance1},
                 {dispatch_group,instance1},
                 {ip, Ip},
                 {port, Port},
                 {log_dir, "priv/log"},
                 {dispatch, Dispatch}],
    

    So, for multiple instances you might have something like this for your supervisor spec:

    WebConfig1 = [{name,instance1},
                  {dispatch_group,instance1},
                  {ip, Ip},
                  {port, Port},
                  {log_dir, "priv/log"},
                  {dispatch, Dispatch}],
    WebConfig2 = [{name,instance2},
                  {dispatch_group,instance2},
                  {ip, Ip},
                  {port, Port+1},
                  {log_dir, "priv/log"},
                  {dispatch, Dispatch}],
    Web1 = {instance1,
            {webmachine_mochiweb, start, [WebConfig1]},
            permanent, 5000, worker, [mochiweb_socket_server]},
    Web2 = {instance2,
            {webmachine_mochiweb, start, [WebConfig2]},
            permanent, 5000, worker, [mochiweb_socket_server]},
    Processes = [Web1, Web2],
    {ok, { {one_for_one, 10, 10}, Processes} }.
    

    One other thing: judging from the name application_sup appearing in your question, you may have run the webmachine ./scripts/new_webmachine.sh and specified the application name as application. If so, don't do this, since application is the name of a key Erlang OTP module, and your code will clash with it and cause all kinds of problems.