Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
vorn committed Apr 7, 2012
0 parents commit cadccdf
Show file tree
Hide file tree
Showing 25 changed files with 513 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
@@ -0,0 +1,3 @@
[submodule "ChicagoBoss"]
path = ChicagoBoss
url = https://github.com/evanmiller/ChicagoBoss.git
1 change: 1 addition & 0 deletions ChicagoBoss
Submodule ChicagoBoss added at 16603b
1 change: 1 addition & 0 deletions Procfile
@@ -0,0 +1 @@
web: ./run.sh
41 changes: 41 additions & 0 deletions README.md
@@ -0,0 +1,41 @@
Running ChicagoBoss (erlang web framework) on Heroku
----------------------------------------------------

N.B. This process was an initial attempt and is subject to change :)

To create a new project from scratch:

1. Create a top level project directory. Add an empty ebin/ directory.
- (N.B. also create a dummy file to commit to git)
2.
git init; git submodule add https://github.com/evanmiller/ChicagoBoss.git ChicagoBoss
3.
cd ChicagoBoss; make; make app PROJECT=myapp
4. Add Procfile, run.sh from this project - edit project name in run.sh
5. Edit myapp/init.sh - add the following sections: (running erl with the -sname param causes heroku startup to fail)

'start-no-sname')
# Start Boss in production mode with no -sname parameter
echo "starting boss in production mode..."
START=$(./rebar boss c=start_cmd|grep -v "==>"|perl -pe 's/-sname\s+\S+//')
$START
;;

'start-dev-no-sname')
# Start Boss in development mode
START_DEV=$(./rebar boss c=start_dev_cmd|grep -v "==>"|perl -pe 's/-sname\s+\S+//')
$START_DEV
;;

6. Deploy! (git add .; git push heroku master)



A few caveats:
- This is based on using the heroku supplied erlang buildpack at: https://github.com/heroku/heroku-buildpack-erlang
- A better solution would be to modify the buildpack to build CB at the compile stage (as opposed to the run stage)
- As such, the above solution may crash at the first deploy due to the app not starting within 60secs. Run:
heroku logs -t
in a seperate window to keep an eye on the deployment/startup process.


10 changes: 10 additions & 0 deletions cb-heroku.iml
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

1 change: 1 addition & 0 deletions ebin/.empty
@@ -0,0 +1 @@
This ebin dir is empty - it exists to convince Heroku that this is an Erlang app.
19 changes: 19 additions & 0 deletions myapp/boss.config
@@ -0,0 +1,19 @@
[{boss, [
{path, "/Users/vorn/dev/erl/cb-heroku/ChicagoBoss"},
{vm_cookie, "abc123"},
{applications, [myapp]},
{db_host, "localhost"},
{db_port, 1978},
{db_adapter, mock},
{log_dir, "log"},
{server, misultin},
{port, 8001},
{session_adapter, mock},
{session_key, "_boss_session"},
{session_exp_time, 525600}
]},
{ myapp, [
{path, "../myapp"},
{base_url, "/"}
]}
].
8 changes: 8 additions & 0 deletions myapp/init-dev.sh
@@ -0,0 +1,8 @@
#!/usr/bin/env sh
#
# Chicago Boss Dev Init System
# easy start dev server (most common task)

cd `dirname $0`

./init.sh start-dev
68 changes: 68 additions & 0 deletions myapp/init.sh
@@ -0,0 +1,68 @@
#!/usr/bin/env sh
#
# Chicago Boss Init System
#
# @author: Jose Luis Gordo Romero <jgordor@gmail.com>
#
# -------------------------------------------------------------------
# The shell commands are automatically generated by the boss rebar
# plugin/driver, all configuration params and paths are in boss.config
# -------------------------------------------------------------------

cd `dirname $0`

case "${1:-''}" in
'start')
# Start Boss in production mode
echo "starting boss in production mode..."
START=$(./rebar boss c=start_cmd|grep -v "==>")
$START
;;

'start-dev')
# Start Boss in development mode
START_DEV=$(./rebar boss c=start_dev_cmd|grep -v "==>")
$START_DEV
;;

'start-standalone')
# Start Boss in production mode with no -sname parameter
echo "starting boss in production mode..."
START=$(./rebar boss c=start_cmd|grep -v "==>"|perl -pe 's/-sname\s+\S+//')
$START
;;

'start-dev-standalone')
# Start Boss in development mode
START_DEV=$(./rebar boss c=start_dev_cmd|grep -v "==>"|perl -pe 's/-sname\s+\S+//')
$START_DEV
;;

'stop')
# Stop Boss daemon
echo "stopping boss..."
STOP=$(./rebar boss c=stop_cmd|grep -v "==>")
# After hours of shell quoting problems with the erl command,
# eval with the command quoted works!!!
eval "$STOP"
;;

'reload')
# Boss hot code reload <-- only the actual node, not the entire cluster
echo "Hot code reload, (WARN: Only this node)"
RELOAD=$(./rebar boss c=reload_cmd|grep -v "==>")
eval "$RELOAD"
;;

'restart')
# Boss complete restart
echo "Restarting (stop-start) boss..."
$0 stop
$0 start
;;
*)
echo "Chicago Boss Boot System"
echo "Usage: $SELF start|start-dev|stop|reload|restart"
exit 1
;;
esac
97 changes: 97 additions & 0 deletions myapp/priv/init/myapp_01_news.erl
@@ -0,0 +1,97 @@
-module(myapp_01_news).

-export([init/0, stop/1]).

% This script is first executed at server startup and should
% return a list of WatchIDs that should be cancelled in the stop
% function below (stop is executed if the script is ever reloaded).
init() ->
{ok, []}.

stop(ListOfWatchIDs) ->
lists:map(fun boss_news:cancel_watch/1, ListOfWatchIDs).

%%%%%%%%%%% Ideas
% boss_news:watch("user-42.*",
% fun
% (updated, {Donald, 'location', OldLocation, NewLocation}) ->
% ;
% (updated, {Donald, 'email_address', OldEmail, NewEmail})
% end),
%
% boss_news:watch("user-*.status",
% fun(updated, {User, 'status', OldStatus, NewStatus}) ->
% Followers = User:followers(),
% lists:map(fun(Follower) ->
% Follower:notify_status_update(User, NewStatus)
% end, Followers)
% end),
%
% boss_news:watch("users",
% fun
% (created, NewUser) ->
% boss_mail:send(?WEBSITE_EMAIL_ADDRESS,
% ?ADMINISTRATOR_EMAIL_ADDRESS,
% "New account!",
% "~p just created an account!~n",
% [NewUser:name()]);
% (deleted, OldUser) ->
% ok
% end),
%
% boss_news:watch("forum_replies",
% fun
% (created, Reply) ->
% OrignalPost = Reply:original_post(),
% OriginalAuthor = OriginalPost:author(),
% case OriginalAuthor:is_online() of
% true ->
% boss_mq:push(OriginalAuthor:comet_channel(), <<"Someone replied!">>);
% false ->
% case OriginalAuthor:likes_email() of
% true ->
% boss_mail:send("website@blahblahblah",
% OriginalAuthor:email_address(),
% "Someone replied!"
% "~p has replied to your post on ~p~n",
% [(Reply:author()):name(), OriginalPost:title()]);
% false ->
% ok
% end
% end;
% (_, _) -> ok
% end),
%
% boss_news:watch("forum_categories",
% fun
% (created, NewCategory) ->
% boss_mail:send(?WEBSITE_EMAIL_ADDRESS,
% ?ADMINISTRATOR_EMAIL_ADDRESS,
% "New category: "++NewCategory:name(),
% "~p has created a new forum category called \"~p\"~n",
% [(NewCategory:created_by()):name(), NewCategory:name()]);
% (_, _) -> ok
% end),
%
% boss_news:watch("forum_category-*.is_deleted",
% fun
% (updated, {ForumCategory, 'is_deleted', false, true}) ->
% ;
% (updated, {ForumCategory, 'is_deleted', true, false}) ->
% end).

% Invoking the API directly:
%boss_news:deleted("person-42", OldAttrs),
%boss_news:updated("person-42", OldAttrs, NewAttrs),
%boss_news:created("person-42", NewAttrs)

% Invoking the API via HTTP (with the admin application installed):
% POST /admin/news_api/deleted/person-42
% old[status] = something

% POST /admin/news_api/updated/person-42
% old[status] = blah
% new[status] = barf

% POST /admin/news_api/created/person-42
% new[status] = something
20 changes: 20 additions & 0 deletions myapp/priv/myapp.routes
@@ -0,0 +1,20 @@
% Routes file.

% Formats:
% {"/some/route", [{controller, "Controller"}, {action, "Action"}]}.
% {"/some/route", [{controller, "Controller"}, {action, "Action"}, {id, "42"}]}.
% {"/some/route", [{application, some_app}, {controller, "Controller"}, {action, "Action"}, {id, "42"}]}.
% {404, [{controller, "Controller"}, {action, "Action"}]}.
% {404, [{controller, "Controller"}, {action, "Action"}, {id, "42"}]}.
% {404, [{application, some_app}, {controller, "Controller"}, {action, "Action"}, {id, "42"}]}.
%
% Note that routing across applications results in a 302 redirect.

% Front page
% {"/", [{controller, "world"}, {action, "hello"}]}.

% 404 File Not Found handler
% {404, [{controller, "world"}, {action, "lost"}]}.

% 500 Internal Error handler (only invoked in production)
% {500, [{controller, "world"}, {action, "calamity"}]}.

0 comments on commit cadccdf

Please sign in to comment.