Skip to content

Instantly share code, notes, and snippets.

@ToddG
Created October 14, 2012 16:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ToddG/3889116 to your computer and use it in GitHub Desktop.
Save ToddG/3889116 to your computer and use it in GitHub Desktop.
shapesmith notes

shapesmith notes

license

http://www.apache.org/licenses/LICENSE-2.0

Allows public/private derivations.

erlang

deps

  • TODO: discuss each of the cool libraries that are brought in.
  • TODO: discuss why the various (older) revisions are being used

open questions

Question: why is webmachine both started as a dependency and started as a worker under api_sup.erl?

Question: [33] Ip = case os:getenv("WEBMACHINE_IP") of false -> "0.0.0.0"; Any -> Any end,

overview

api.app.src

* project configuration
-> 
api.erl
    * start dependencies
        inets
        crypto
        bcrypt
        lager
        mochiweb
        folsom
        webmachine
        worker_master
    * starts app
    -> 
    api_app.erl
        * starts a supervisor
        -> 
        api_sup.erl
            * loads config for webmachine
            * specifies a supervision strategy for webmachine
            * launches webmachine as a worker

Question: why is webmachine both started as a dependency and started as a worker under api_sup.erl?

impl

  1. api.erl
  1. api_app.erl
  • starts api_sup.erl
  1. api_sup.erl

Question: [33] Ip = case os:getenv("WEBMACHINE_IP") of false -> "0.0.0.0"; Any -> Any end,

Why grab the ip address from an env var? isn't there a cleaner way to do this? could you simply query webmachine and ask it it's ip address? or if you have to store it, store it in an ets/dets/mnesia/riak?

Read erlang terms sep by '.' from a file

f.txt:  {person, "kalle", 25}.
        {person, "pelle", 30}.
1> file:consult("f.txt").
{ok,[{person,"kalle",25},{person,"pelle",30}]}
  • filename:join(http://erldocs.com/R15B/stdlib/filename.html?i=0&search=filename:join#join/1)

    Joins a list of file name Components with directory separators. If one of the elements of Components includes an absolute path, for example "/xxx", the preceding elements, if any, are removed from the result.

    The result is "normalized": Redundant directory separators are removed. In Windows, all directory separators are forward slashes and the drive letter is in lower case.

17> filename:join(["/usr", "local", "bin"]).
"/usr/local/bin"
18> filename:join(["a/b///c/"]).
"a/b/c"

6> filename:join(["B:a\\b///c/"]). % Windows
"b:a/b/c"

Returns the directory part of Filename

13> filename:dirname("/usr/src/kalle.erl").
"/usr/src"
14> filename:dirname("kalle.erl").
"."

If the module is not loaded, this function searches the code path for the first file which contains object code for Module and returns the absolute file name

  • [34] loads an erlang 'properties' file from nodes/apps/api/priv/dispatch.conf
{[], api_home_redirect_resource, []}.
{["static", '*'], api_fs_resource, [{root, "../"}]}.

{["signup"], api_signup_resource, []}.
{["signin"], api_signin_resource, []}.
{["signout"], api_signout_resource, []}.
<snip>
  • application:get_env(http://www.erlang.org/doc/apps/kernel/application.html#get_env-1)

    Returns the value of the configuration parameter Par for Application. If the application argument is omitted, it defaults to the application of the calling process.

    If the specified application is not loaded, or the configuration parameter does not exist, or if the process executing the call does not belong to any application, the function returns undefined.

  • Q: [37] get the api/port value... where was this set? A: in the api.app.src::env stanza.

Extra stuff elided for clarity...

{application, api, [{env, [ {port, 8000}]} ]}.
  • [38] create a configuration object
  • [44] Q: really not sure what's going on here,

supervisor definition

http://www.erlang.org/doc/man/supervisor.html

supervisor:init

Module:init(Args) -> Result
Types:
Args = term()
Result = {ok,{{RestartStrategy,MaxR,MaxT},[ChildSpec]}} | ignore
 RestartStrategy = strategy()
 MaxR = integer()>=0
 MaxT = integer()>0
 ChildSpec = child_spec()

supervisor child_spec

This is the type definition of a child specification:

child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
 Id = term()
 StartFunc = {M,F,A}
  M = F = atom()
  A = [term()]
 Restart = permanent | transient | temporary
 Shutdown = brutal_kill | int()>0 | infinity
 Type = worker | supervisor
 Modules = [Module] | dynamic
  Module = atom()

So, we should see this returned:

{ok,{{RestartStrategy,MaxR,MaxT},[{Id,StartFunc,Restart,Shutdown,Type,Modules}]}}

So let's break this down:

{ok, { {one_for_one, 10, 10}, [Web]} }.

which is

{ok, { {one_for_one, 10, 10}, [{webmachine_mochiweb,
       {webmachine_mochiweb, start, [WebConfig]},
       permanent, 5000, worker, [webmachine_mochiweb]}]} }.

which translates to

    {ok,  // atom
    
    { 
        {
            one_for_one,    // restart strategy
            10,             // MaxR
            10              // MaxT
                            // To prevent a supervisor from getting into an infinite loop of child process terminations and restarts, a maximum restart frequency is defined using two integer values MaxR and MaxT. If more than MaxR restarts occur within MaxT seconds, the supervisor terminates all child processes and then itself. 
        }, 
        [
            {webmachine_mochiweb,      // id is a name that is used to identify the child by the supervisor 
           {webmachine_mochiweb, start, [WebConfig]}, // start function as MFA
           permanent,                   // defines restart strategy
           5000,                        //  An integer timeout value means that the supervisor will tell the child process to terminate by calling exit(Child,shutdown) and then wait for an exit signal with reason shutdown back from the child process. If no exit signal is received within the specified number of milliseconds, the child process is unconditionally terminated using exit(Child,kill).
           worker,                      // Type specifies if the child process is a supervisor or a worker.
           [webmachine_mochiweb]        // Modules is used by the release handler during code replacement to determine which processes are using a certain module. As a rule of thumb Modules should be a list with one element [Module], where Module is the callback module, if the child process is a supervisor, gen_server or gen_fsm. If the child process is an event manager (gen_event) with a dynamic set of callback modules, Modules should be dynamic. See OTP Design Principles for more information about release handling.
        }]} }.

web

TODO

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment