Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add more type specs guided by Dialyzer. #73

Closed
wants to merge 1 commit into from

2 participants

@tmcgilchrist

Basically I added further type specs using erlc flag +warn_missing_spec then improved those specs based on the Dialyzer flag -Wunderspecs.

+warn_missing_spec isn't complaining anymore about missing specs, which is nice.

-Wunderspecs has a few complaints but they don't appear to be too bad.

Dialyser continues to complain about Unknown functions. Seems like it's not finding the code in the deps directory.

Rebased against csm-cluster-management as requested

Apologies for the noise in the Ember template file, it appears to be just whitespace.

include/riak_control.hrl
@@ -76,6 +76,7 @@
replacement :: node()
}).
+-type partition() :: #partition_info{}.
-type partitions() :: [#partition_info{}].
@cmeiklejohn Collaborator

Maybe change this to [partition()]?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/admin_cluster.erl
@@ -226,12 +226,14 @@ merge_transitions(Nodes, Changes, Claim) ->
end, [], Nodes).
%% @doc Merge change into member info record.
--spec apply_changes(#member_info{}, list(), list()) -> #member_info{}.
+%% -spec apply_changes(#member_info{}, list(), list()) -> #member_info{}.
@cmeiklejohn Collaborator

Maybe kill this commented spec?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/admin_cluster.erl
@@ -50,7 +50,7 @@
-include_lib("webmachine/include/webmachine.hrl").
%% @doc Return routes this resource should respond to.
--spec routes() -> list().
+-spec routes() -> [{[[any()],...],'admin_cluster',[]},...].
@cmeiklejohn Collaborator

I'd check out webmachine and pull the specs they are using for defining routes, which is a bit more specific and probably more useful.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/base64url.erl
@@ -34,24 +34,37 @@
mime_decode/1,
mime_decode_to_string/1]).
+-spec decode(binary()|string()) ->
@cmeiklejohn Collaborator

binary() | string() is repeated too many times in this file. We should create a type in include/riak_control.hrl.

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

@tmcgilchrist while this PR adds a ton of missing specs, it also introduces a bunch of new Dialyzer errors for me. I'm assuming one possible reason for this is because the specs are more specific, or they are incorrect in some cases.

It also appears that some of the newly added specs might have been taken from the success typings returned from Dialyzer -- while these specs are technically correct because they are generated through case-analysis, I'd prefer to write more specific specs which express the application level logic and concerns.

src/admin_cluster.erl
@@ -226,12 +226,14 @@ merge_transitions(Nodes, Changes, Claim) ->
end, [], Nodes).
%% @doc Merge change into member info record.
--spec apply_changes(#member_info{}, list(), list()) -> #member_info{}.
+%% -spec apply_changes(#member_info{}, list(), list()) -> #member_info{}.
+-spec apply_changes(#member_info{},[any(),...],[any()]) ->
@cmeiklejohn Collaborator

This spec could probably be a bit more specific and/or expressive.

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

Thanks for the feedback @cmeiklejohn, completely agree. I'll work on this PR a bit more.

@tmcgilchrist tmcgilchrist Add more type specs guided by Dialyzer.
Basically I added further type specs using erlc flag +warn_missing_spec then improved those specs based on the Dialyzer flag -Wunderspecs.
b36ca17
@tmcgilchrist tmcgilchrist commented on the diff
((11 lines not shown))
build_plt: compile
- dialyzer --build_plt --output_plt $(PLT) --apps $(APPS)
+ dialyzer --build_plt --output_plt $(PLT) --apps $(APPS) deps/webmachine/ebin deps/mochiweb/ebin deps/erlydtl/ebin

Background on this, initially I was pulling in everything under deps but this was making dialyzer crash so I've just included the most important dependencies.

@cmeiklejohn Collaborator

Agreed, :+1: on this. I've witnessed the dialyzer crash myself and it's somehow related to the riak_pb dependency pulled in by riak_core as far as I can tell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@tmcgilchrist tmcgilchrist commented on the diff
src/admin_routes.erl
@@ -23,24 +23,28 @@
-export([admin_route/1,
ring_route/0,
ring_route/1,
- vnode_route/0,
- vnode_route/1,
nodes_route/0,

These functions weren't being used anywhere so I removed them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@cmeiklejohn cmeiklejohn commented on the diff
src/rebar_js_concatenator_plugin.erl
@@ -71,10 +71,14 @@
-export([concatenate/1,
concatenate_files/1]).
+-type config() :: [{atom(), string()|list(string())}].
@cmeiklejohn Collaborator

I'd love to see these changes made to cmeiklejohn/riak_js_concatenator_plugin, and then the new dependency pulled in.

No worries. I'm not seeing a public repo for http://github.com/cmeiklejohn/riak_js_concatenator_plugin
Have you made it public yet?

@cmeiklejohn Collaborator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@cmeiklejohn cmeiklejohn commented on the diff
src/rebar_js_handlebars_plugin.erl
@@ -76,10 +76,14 @@
-export([handlebars/4]).
+-type config() :: [{atom(), string()|list(string())}].
@cmeiklejohn Collaborator

Same here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@cmeiklejohn cmeiklejohn commented on the diff
src/rebar_js_stylus_plugin.erl
@@ -61,11 +61,14 @@
-export([compile/2,
clean/2]).
+-type config() :: [{atom(), string()|list(string())}].
@cmeiklejohn Collaborator

And here. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@tmcgilchrist tmcgilchrist referenced this pull request in cmeiklejohn/rebar_js_concatenator_plugin
Open

Add type specs. #3

@cmeiklejohn
Collaborator

Tim, there's been quite a few changes since this was opened. Do you mind reopening this against the 1.4 branch?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 15, 2013
  1. @tmcgilchrist

    Add more type specs guided by Dialyzer.

    tmcgilchrist authored
    Basically I added further type specs using erlc flag +warn_missing_spec then improved those specs based on the Dialyzer flag -Wunderspecs.
This page is out of date. Refresh to see the latest.
View
11 Makefile
@@ -27,14 +27,14 @@ docs:
./rebar skip_deps=true doc
APPS = kernel stdlib sasl erts ssl tools os_mon runtime_tools crypto inets \
- xmerl webtool eunit syntax_tools compiler
+ xmerl webtool eunit syntax_tools compiler mnesia public_key snmp
PLT = $(HOME)/.riak_control_dialyzer_plt
check_plt: compile
- dialyzer --check_plt --plt $(PLT) --apps $(APPS)
+ dialyzer --check_plt --plt $(PLT) --apps $(APPS) deps/webmachine/ebin deps/mochiweb/ebin deps/erlydtl/ebin
build_plt: compile
- dialyzer --build_plt --output_plt $(PLT) --apps $(APPS)
+ dialyzer --build_plt --output_plt $(PLT) --apps $(APPS) deps/webmachine/ebin deps/mochiweb/ebin deps/erlydtl/ebin

Background on this, initially I was pulling in everything under deps but this was making dialyzer crash so I've just included the most important dependencies.

@cmeiklejohn Collaborator

Agreed, :+1: on this. I've witnessed the dialyzer crash myself and it's somehow related to the riak_pb dependency pulled in by riak_core as far as I can tell.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
dialyzer: compile
@echo
@@ -44,13 +44,10 @@ dialyzer: compile
@sleep 1
dialyzer -Wno_return -Wunmatched_returns --plt $(PLT) ebin
-cleanplt:
+clean_plt:
@echo
@echo "Are you sure? It takes about 1/2 hour to re-build."
@echo Deleting $(PLT) in 5 seconds.
@echo
sleep 5
rm $(PLT)
-
-typer:
- typer --annotate -I ../ --plt $(PLT) -r src
View
2  include/riak_control.hrl
@@ -53,6 +53,8 @@
-type change() :: {node(), action()}.
+-type base64url() :: binary() | string().
+
-record(partition_info,
{ index :: index(),
partition :: integer(),
View
2  priv/admin/js/generated/templates.js
@@ -1,6 +1,6 @@
Ember.TEMPLATES['application'] = Ember.Handlebars.compile('<div id="header"> <div id="navbar"> <a id="riak-control-logo"></a> <nav> <ul id="nav-ul"> <li id="nav-ring" class="nav-li"><a {{action showRing href=true}} class="gui-text-bold nav-item"></a><span class="indicator"></span></li> <li id="nav-cluster" class="nav-li"><a {{action showCluster href=true}} class="gui-text-bold nav-item"></a><span class="indicator"></span></li> <li id="nav-snapshot" class="nav-li"><a {{action showSnapshot href=true}} class="gui-text-bold nav-item"></a><span class="indicator"></span></li> </ul> </nav> </div></div><div id="wrapper" class="split gui-text"> <section id="content-well">{{outlet}}</section> <footer> <div class="side-line"></div> <div class="title-box"> <span class="vert-border-left"></span> <a id="basho-logo" href="http://www.basho.com" target="_blank"><img src="/admin/ui/images/basho-logo.png" alt=""/></a> <span class="vert-border-right"></span> </div> <div class="side-line"></div> <div class="clear"></div> <footer></div><!-- #wrapper --><div id="tooltips" class="hide"> <div id="display-tips" class="gui-text"></div></div>');
Ember.TEMPLATES['snapshot'] = Ember.Handlebars.compile('<div id="snapshot-page"> <section id="title-container"> <div class="side-line"></div> <div class="title-box"> <span class="vert-border-left"></span> <h1 id="snapshot-headline" class="gui-headline-bold page-title">Current Snapshot</h1> <span class="vert-border-right"></span> </div> <div class="side-line"></div> <div class="clear"></div> </section> <div class="relative health-info"> {{#if healthyCluster}} <div id="healthy-cluster"> <img id="health-indicator" src="/admin/ui/images/healthy-cluster.png" alt="" /> <section> <h2 class="gui-headline-bold has-cut">Your cluster is healthy.</h2> <h3 class="">You currently have...</h3> <ul class="gui-text bulleted"> <li><span class="emphasize monospace">0</span> Unreachable nodes</li> <li><span class="emphasize monospace">0</span> Incompatible nodes</li> <li><span class="emphasize monospace">0</span> Nodes marked as down</li> <li><span class="emphasize monospace">0</span> Nodes experiencing low memory</li> <li>Nothing to worry about because Riak is your friend</li> </ul> </section> </div> {{else}} <div id="unhealthy-cluster"> <img id="health-indicator" src="/admin/ui/images/unhealthy-cluster.png" alt="" /> <section> <h2 class="gui-headline-bold has-cut">Your cluster has problems.</h2> {{#if areUnreachableNodes}} <!-- Unreachable Nodes List --> <h3 id="unreachable-nodes-title" class="">The following nodes are currently unreachable:</h3> <ul id="unreachable-nodes-list" class="gui-text bulleted monospace"> {{#each unreachableNodes}} <li><a class="go-to-cluster" {{action showCluster href=true}}>{{name}}</a></li> {{/each}} </ul> {{/if}} {{#if areIncompatibleNodes}} <!-- Incompatible Nodes List --> <h3 id="incompatible-nodes-title" class="">The following nodes are currently incompatible with Riak Control:</h3> <ul id="incompatible-nodes-list" class="gui-text bulleted monospace"> {{#each incompatibleNodes}} <li><a class="go-to-cluster" {{action showCluster href=true}}>{{name}}</a></li> {{/each}} </ul> {{/if}} {{#if areDownNodes}} <!-- Down Nodes List --> <h3 id="down-nodes-title" class="">The following nodes are currently marked down:</h3> <ul id="down-nodes-list" class="gui-text bulleted monospace"> {{#each downNodes}} <li><a class="go-to-cluster" {{action showCluster href=true}}>{{name}}</a></li> {{/each}} </ul> {{/if}} {{#if areLowMemNodes}} <!-- Low-Mem Nodes List --> <h3 id="low_mem-nodes-title" class="">The following nodes are currently experiencing low memory:</h3> <ul id="low_mem-nodes-list" class="gui-text bulleted monospace"> {{#each lowMemNodes}} <li><a class="go-to-cluster" {{action showCluster href=true}}>{{name}}</a></li> {{/each}} </ul> {{/if}} </section> </div> {{/if}} </div> </div>');
-Ember.TEMPLATES['cluster'] = Ember.Handlebars.compile('<div id="cluster-page"> <section id="title-container"> <div class="side-line"></div> <div class="title-box"> <span class="vert-border-left"></span> <h1 id="cluster-headline" class="gui-headline-bold page-title">Cluster Management</h1> <span class="vert-border-right"></span> </div> <div class="side-line"></div> <div class="clear"></div> </section> <div id="add-node"> <h2 class="gui-headline">Join Nodes</h2> <span class="gui-text-flat italic">Type a node name or list of names separated by commas.</span> <table class="add-node-table"> <tr class="no-highlight"> <td id="add-node-box"> {{view RiakControl.AddNodeView id="node-to-add"}} </td> <td class="button-column"> <a class="gui-point-button gui-text-bold right" {{action addNode target="controller"}}> <span class="gui-button-msg">ADD NODES</span> </a> </td> </tr> </table> {{#if errorMessage}} <div class="error-message"> <a class="close-error gui-text" {{action hideError target="controller"}}></a> <a class="error-text offline gui-text-flat">{{errorMessage}}</a> </div> {{/if}} </div><!-- #add-node --> <div id="current-area"> <h2 class="gui-headline"> Current Cluster <span id="total-number" class="gui-text-flat italic"></span><br/> </h2> <section id="node-list"> {{#if controller.isLoading}} <div class="spinner-box"> <img id="cluster-spinner" class="spinner" src="/admin/ui/images/spinner.gif"> <h4 class="gui-headline-bold">Loading...</h4> </div> {{else}} <ul class="list-header"> <li class="item1"><h4 class="gui-headline-bold">Actions</h4></li> <li class="item2"><h4 class="gui-headline-bold">Name &amp; Status</h4></li> <li class="item3"><h4 class="gui-headline-bold">Partitions</h4></li> <li class="item4"><h4 class="gui-headline-bold">RAM Usage</h4></li> </ul> <div class="clear"></div> {{collection RiakControl.CurrentClusterView contentBinding="activeCurrentCluster"}} {{/if}} </section> </div> <div id="area-separator"> <div class="vert-line"></div> </div> <div id="planned-area"> <h2 class="gui-headline"> Staged Changes <span class="gui-text-flat italic">(Your new cluster after convergence.)</span> </h2> {{#if controller.displayPlan}} <section id="planned-list" class=""> <ul class="list-header"> <li class="item1"><h4 class="gui-headline-bold">Name &amp; Status</h4></li> <li class="item2"><h4 class="gui-headline-bold">Partitions</h4></li> <li class="item3"><h4 class="gui-headline-bold">Action</h4></li> <li class="item4"><h4 class="gui-headline-bold">Replacement</h4></li> </ul> <div class="clear"></div> {{collection RiakControl.StagedClusterView contentBinding="activeStagedCluster"}} </section> <div class="accept-plan"> <div class="gui-checkbox-wrapper"> <label for="confirmed-check">This plan is correct.</label> <input class="gui-checkbox" type="checkbox" name="confirmed" id="confirmed-check" value="accept"/> </div> <a id="commit-button" class="gui-point-button-right gui-text-bold right" {{action commitPlan target="controller"}}> <span class="gui-button-msg">COMMIT</span> </a> </div> <div class="clear-plan-box"> <span class="gui-text-flat serif"> Changed your mind? Click this button to remove all staged changes. </span> <a class="gui-rect-button gui-text-bold" {{action clearPlan target="controller"}}> <span class="gui-button-msg">CLEAR PLAN</span> </a> </div> {{else}} <section id="planned-list"> <div class="spinner-box"> {{#if controller.ringNotReady}} <h4 class="gui-headline-bold"> Cannot plan until cluster state has converged. Check "Ring Ready" in "riak-admin ring_status". </h4> {{else}} {{#if controller.legacyRing}} <h4 class="gui-headline-bold">You are currently running a legacy version of Riak that does not support staged changes.</h4> {{else}} {{#if controller.emptyPlan}} <h4 class="gui-headline-bold">Currently no staged changes to display.</h4> {{else}} {{#if controller.isLoading}} <img id="cluster-spinner" class="spinner" src="/admin/ui/images/spinner.gif"> <h4 class="gui-headline-bold">Loading...</h4> {{/if}} {{/if}} {{/if}} {{/if}} </div> </section> {{/if}} </div> <div class="clear"></div> </div>');
+Ember.TEMPLATES['cluster'] = Ember.Handlebars.compile('<div id="cluster-page"> <section id="title-container"> <div class="side-line"></div> <div class="title-box"> <span class="vert-border-left"></span> <h1 id="cluster-headline" class="gui-headline-bold page-title">Cluster Management</h1> <span class="vert-border-right"></span> </div> <div class="side-line"></div> <div class="clear"></div> </section> <div id="add-node"> <h2 class="gui-headline">Join Nodes</h2> <span class="gui-text-flat italic">Type a node name or list of names separated by commas.</span> <table class="add-node-table"> <tr class="no-highlight"> <td id="add-node-box"> {{view RiakControl.AddNodeView id="node-to-add"}} </td> <td class="button-column"> <a class="gui-point-button gui-text-bold right" {{action addNode target="controller"}}> <span class="gui-button-msg">ADD NODES</span> </a> </td> </tr> </table> {{#if errorMessage}} <div class="error-message"> <a class="close-error gui-text" {{action hideError target="controller"}}></a> <a class="error-text offline gui-text-flat">{{errorMessage}}</a> </div> {{/if}} </div><!-- #add-node --> <div id="current-area"> <h2 class="gui-headline"> Current Cluster <span id="total-number" class="gui-text-flat italic"></span><br/> </h2> <section id="node-list"> {{#if controller.isLoading}} <div class="spinner-box"> <img id="cluster-spinner" class="spinner" src="/admin/ui/images/spinner.gif"> <h4 class="gui-headline-bold">Loading...</h4> </div> {{else}} <ul class="list-header"> <li class="item1"><h4 class="gui-headline-bold">Actions</h4></li> <li class="item2"><h4 class="gui-headline-bold">Name &amp; Status</h4></li> <li class="item3"><h4 class="gui-headline-bold">Partitions</h4></li> <li class="item4"><h4 class="gui-headline-bold">RAM Usage</h4></li> </ul> <div class="clear"></div> {{collection RiakControl.CurrentClusterView contentBinding="activeCurrentCluster"}} {{/if}} </section> </div> <div id="area-separator"> <div class="vert-line"></div> </div> <div id="planned-area"> <h2 class="gui-headline"> Staged Changes <span class="gui-text-flat italic">(Your new cluster after convergence.)</span> </h2> {{#if controller.displayPlan}} <section id="planned-list" class=""> <ul class="list-header"> <li class="item1"><h4 class="gui-headline-bold">Name &amp; Status</h4></li> <li class="item2"><h4 class="gui-headline-bold">Partitions</h4></li> <li class="item3"><h4 class="gui-headline-bold">Action</h4></li> <li class="item4"><h4 class="gui-headline-bold">Replacement</h4></li> </ul> <div class="clear"></div> {{collection RiakControl.StagedClusterView contentBinding="activeStagedCluster"}} </section> <div class="accept-plan"> <div class="gui-checkbox-wrapper"> <label for="confirmed-check">This plan is correct.</label> <input class="gui-checkbox" type="checkbox" name="confirmed" id="confirmed-check" value="accept"/> </div> <a id="commit-button" class="gui-point-button-right gui-text-bold right" {{action commitPlan target="controller"}}> <span class="gui-button-msg">COMMIT</span> </a> </div> <div class="clear-plan-box"> <span class="gui-text-flat serif"> Changed your mind? Click this button to remove all staged changes. </span> <a class="gui-rect-button gui-text-bold" {{action clearPlan target="controller"}}> <span class="gui-button-msg">CLEAR PLAN</span> </a> </div> {{else}} <section id="planned-list"> <div class="spinner-box"> {{#if controller.ringNotReady}} <h4 class="gui-headline-bold"> Cannot plan until cluster state has converged. Check "Ring Ready" in "riak-admin ring_status". </h4> {{else}} {{#if controller.legacyRing}} <h4 class="gui-headline-bold">You are currently running a legacy version of Riak that does not support staged changes.</h4> {{else}} {{#if controller.emptyPlan}} <h4 class="gui-headline-bold">Currently no staged changes to display.</h4> {{else}} {{#if controller.isLoading}} <img id="cluster-spinner" class="spinner" src="/admin/ui/images/spinner.gif"> <h4 class="gui-headline-bold">Loading...</h4> {{/if}} {{/if}} {{/if}} {{/if}} </div> </section> {{/if}} </div> <div class="clear"></div></div>');
Ember.TEMPLATES['ring'] = Ember.Handlebars.compile('<div id="ring-page"> <section id="title-container"> <div class="side-line"></div> <div class="title-box"> <span class="vert-border-left"></span> <h1 id="ring-headline" class="gui-headline-bold page-title">Current Ring</h1> <span class="vert-border-right"></span> </div> <div class="side-line"> {{outlet partitionFilter}} </div> <div class="clear"></div> </section> <ul class="pagination gui-text"> <li name="prev"><span class="paginator" {{action prevPage href=true target="controller"}}>Prev</span></li> {{#each pages}} {{view RiakControl.PaginationItemView contentBinding="this"}} {{/each}} <li name="next"><span class="paginator" {{action nextPage href=true target="controller"}}>Next</span></li> </ul> <div class="cut"></div> <div id="partition-list"> <table class="list-table" id="ring-table"> <thead> <tr class="table-head has-cut"> <th><h3>#</h3></th> <th><h3>Owner Node</h3></th> <th><h3>KV</h3></th> <th><h3>Pipe</h3></th> <th><h3>Search</h3></th> </tr> </thead> {{#collection RiakControl.PartitionView contentBinding="controller.paginatedContent"}} {{#with view.content}} <td class="partition-number gui-text">{{i}}</td> <td class="owner-box gui-text"> <div class="owner gui-field">{{node}}</div> <div class="partition-index hide">{{index}}</div> </td> {{/with}} {{#with view}} <td class="kv-box gui-text"> <a {{bindAttr class="kvIndicator lightClasses"}}> <span class="kv-status">{{kvStatus}}</span> <span class="hide fallback-to"></span> </a> </td> <td class="pipe-box gui-text"> <a {{bindAttr class="pipeIndicator lightClasses"}}> <span class="pipe-status">{{pipeStatus}}</span> <span class="hide fallback-to"></span> </a> </td> <td class="search-box gui-text"> <a {{bindAttr class="searchIndicator lightClasses"}}> <span class="search-status">{{searchStatus}}</span> <span class="hide fallback-to"></span> </a> </td> {{/with}} {{/collection}} </table> </div> <div class="cut"></div> <ul class="pagination gui-text"> <li name="prev"><span class="paginator" {{action prevPage href=true target="controller"}}>Prev</span></li> {{#each pages}} {{view RiakControl.PaginationItemView contentBinding="this"}} {{/each}} <li name="next"><span class="paginator" {{action nextPage href=true target="controller"}}>Next</span></li> </ul> </div>');
Ember.TEMPLATES['partition_filter'] = Ember.Handlebars.compile('<div id="ring-filter" class="right"> <div class="gui-dropdown-wrapper"> <div class="gui-dropdown-bg gui-text">Filter by...</div> <div class="gui-dropdown-cap left"></div> {{view RiakControl.PartitionFilterSelectView id="filter" classNames="gui-dropdown" contentBinding="filters" optionLabelPath="content.name" optionValuePath="content.value" prompt="All" selectionBinding="controller.selectedPartitionFilter"}} </div></div>');
Ember.TEMPLATES['pagination_item'] = Ember.Handlebars.compile('{{#with view}}<a {{action paginateRing content href=true}}> <span {{bindAttr class="spanClasses isActive:active"}}>{{content.page_id}}</span></a>{{/with}}');
View
17 src/admin_cluster.erl
@@ -50,7 +50,8 @@
-include_lib("webmachine/include/webmachine.hrl").
%% @doc Return routes this resource should respond to.
--spec routes() -> list().
+-spec routes() -> [webmachine_dispatcher:matchterm()].
+
routes() ->
[{admin_routes:cluster_route(), ?MODULE, []}].
@@ -79,7 +80,7 @@ service_available(ReqData, Context) ->
%% @doc Ensure user has access.
-spec is_authorized(wrq:reqdata(), undefined) ->
- {boolean(), wrq:reqdata(), undefined}.
+ {true | string(), wrq:reqdata(), undefined}.
is_authorized(ReqData, Context) ->
riak_control_security:enforce_auth(ReqData, Context).
@@ -155,7 +156,7 @@ stage_changes(ReqData, Context) ->
end.
%% @doc Stage individual change, used in fold.
--spec stage_individual_change(term())-> ok | {error, term()}.
+-spec stage_individual_change(term()) -> 'ok' | {'error', stage_error()}.
stage_individual_change(Change) ->
try
Node = nodename_to_atom(proplists:get_value(node, Change)),
@@ -226,12 +227,13 @@ merge_transitions(Nodes, Changes, Claim) ->
end, [], Nodes).
%% @doc Merge change into member info record.
--spec apply_changes(#member_info{}, list(), list()) -> #member_info{}.
+-spec apply_changes(#member_info{},[any(),...],[any()]) ->
+ #member_info{}.
apply_changes(Node, Changes, Claim) ->
apply_status_change(apply_claim_change(Node, Claim), Changes).
%% @doc Merge change into member info record.
--spec apply_status_change(#member_info{}, list()) -> #member_info{}.
+-spec apply_status_change(#member_info{}, [any(),...]) -> #member_info{}.
apply_status_change(Node, Changes) ->
Name = Node#member_info.node,
@@ -245,7 +247,7 @@ apply_status_change(Node, Changes) ->
end.
%% @doc Merge change into member info record.
--spec apply_claim_change(#member_info{}, list()) -> #member_info{}.
+-spec apply_claim_change(#member_info{}, [any()]) -> #member_info{}.
apply_claim_change(Node, Claim) ->
Name = Node#member_info.node,
@@ -264,7 +266,8 @@ apply_claim_change(Node, Claim) ->
end.
%% @doc Turn a node into a proper struct for serialization.
--spec jsonify_node(#member_info{}) -> {struct, list()}.
+-spec jsonify_node(#member_info{}) ->
+ {'struct', [{string(), any()}]}.
jsonify_node(Node) ->
LWM=app_helper:get_env(riak_control,low_mem_watermark,0.1),
MemUsed = Node#member_info.mem_used,
View
1  src/admin_nodes.erl
@@ -38,6 +38,7 @@
}).
-type context() :: #ctx{}.
+%% TODO pull these into common header file??
%% mappings to the various content types supported for this resource
-define(CONTENT_TYPES,[{"application/json",to_json}]).
View
5 src/admin_partitions.erl
@@ -46,7 +46,7 @@ routes() ->
[{admin_routes:partitions_route(), ?MODULE, []}].
%% @doc Get partition list at the start of the request.
--spec init(list()) ->
+-spec init([]) ->
{ok, context()}.
init([]) ->
{ok, _, Partitions} = riak_control_session:get_partitions(),
@@ -78,7 +78,8 @@ content_types_provided(ReqData, Context) ->
{?CONTENT_TYPES, ReqData, Context}.
%% @doc Return a list of partitions.
--spec to_json(wrq:reqdata(),context()) -> {iolist(), wrq:reqdata(), context()}.
+-spec to_json(wrq:reqdata(),context()) ->
+ {iolist(), wrq:reqdata(), context()}.
to_json(ReqData, Context) ->
{ok, _, Nodes} = riak_control_session:get_nodes(),
Details = [{struct,
View
16 src/admin_routes.erl
@@ -23,24 +23,28 @@
-export([admin_route/1,
ring_route/0,
ring_route/1,
- vnode_route/0,
- vnode_route/1,
nodes_route/0,

These functions weren't being used anywhere so I removed them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
partitions_route/0,
cluster_route/0]).
%% helper, ensures all routes begin with /admin
+-spec admin_route([string()]) -> [string() ,...].
admin_route(Rest) -> ["admin"|Rest].
%% routes that query/act on partitions
+-spec ring_route([string()])
+ -> [string() ,...].
ring_route(Route) -> admin_route(["ring"|Route]).
-ring_route() -> admin_route(["ring"]).
-%% routes that query/act on individual v-nodes
-vnode_route(Route) -> admin_route(["vnode",partition|Route]).
-vnode_route() -> admin_route(["vnode",partition]).
+-spec ring_route() -> [string() ,...].
+ring_route() -> admin_route(["ring"]).
%% new routes.
+-spec nodes_route() -> [string() ,...].
nodes_route() -> admin_route(["nodes"]).
+
+-spec partitions_route() -> [string() ,...].
partitions_route() -> admin_route(["partitions"]).
+
+-spec cluster_route() -> [string() ,...].
cluster_route() -> admin_route(["cluster"]).
View
1  src/admin_ui_resource.erl
@@ -76,6 +76,7 @@ service_available(RD, #ctx{base_url=Base}=Ctx) ->
riak_control_security:scheme_is_available(RD, Ctx)
end.
+%% @doc Ensure user has access.
-spec is_authorized(wrq:reqdata(), context()) ->
{true | string(), wrq:reqdata(), context()}.
is_authorized(RD, Ctx) ->
View
10 src/base64url.erl
@@ -34,24 +34,33 @@
mime_decode/1,
mime_decode_to_string/1]).
+-include_lib("riak_control/include/riak_control.hrl").
+
+-spec decode(base64url()) -> binary().
decode(Base64url) ->
base64:decode(urldecode(Base64url)).
+-spec decode_to_string(base64url()) -> string().
decode_to_string(Base64url) ->
base64:decode_to_string(urldecode(Base64url)).
+-spec mime_decode(base64url()) -> binary().
mime_decode(Base64url) ->
base64:mime_decode(urldecode(Base64url)).
+-spec mime_decode_to_string(base64url()) -> string().
mime_decode_to_string(Base64url) ->
base64:mime_decode_to_string(urldecode(Base64url)).
+-spec encode(base64url()) -> binary().
encode(Data) ->
urlencode(base64:encode(Data)).
+-spec encode_to_string(base64url()) -> binary().
encode_to_string(Data) ->
urlencode(base64:encode_to_string(Data)).
+-spec urlencode(base64url()) -> binary().
urlencode(Base64) when is_list(Base64) ->
Padded = [urlencode_digit(D) || D <- Base64],
string:strip(Padded, both, $=);
@@ -59,6 +68,7 @@ urlencode(Base64) when is_binary(Base64) ->
Padded = << << (urlencode_digit(D)) >> || <<D>> <= Base64 >>,
binary:replace(Padded, <<"=">>, <<"">>, [global]).
+-spec urldecode(base64url()) -> string()|binary().
urldecode(Base64url) when is_list(Base64url) ->
Prepad = [urldecode_digit(D) || D <- Base64url ],
Padding = padding(Prepad),
View
9 src/rebar_js_concatenator_plugin.erl
@@ -71,10 +71,14 @@
-export([concatenate/1,
concatenate_files/1]).
+-type config() :: [{atom(), string()|list(string())}].
@cmeiklejohn Collaborator

I'd love to see these changes made to cmeiklejohn/riak_js_concatenator_plugin, and then the new dependency pulled in.

No worries. I'm not seeing a public repo for http://github.com/cmeiklejohn/riak_js_concatenator_plugin
Have you made it public yet?

@cmeiklejohn Collaborator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
%% ===================================================================
%% Public API
%% ===================================================================
+-spec compile(config(), _) ->
+ ok.
compile(Config, _AppFile) ->
Options = options(Config),
Concatenations = option(concatenations, Options),
@@ -85,6 +89,8 @@ compile(Config, _AppFile) ->
ConcatOptions} || {Destination, Sources, ConcatOptions} <- Concatenations],
build_each(Targets).
+-spec clean(config(), _) ->
+ ok.
clean(Config, _AppFile) ->
Options = options(Config),
Concatenations = option(concatenations, Options),
@@ -93,8 +99,8 @@ clean(Config, _AppFile) ->
{Destination, _Sources, _ConcatOptions} <- Concatenations],
delete_each(Targets).
-%% @spec concatenate(list()) -> binary()
%% @doc Given a list of sources, concatenate and return.
+-spec concatenate(list()) -> binary().
concatenate(Sources) ->
ListSources = [case is_binary(Source) of true ->
binary_to_list(Source); false -> Source end || Source <- Sources],
@@ -102,6 +108,7 @@ concatenate(Sources) ->
%% @spec concatenate_files(list()) -> list()
%% @doc Given a list of source files, concatenate and return.
+-spec concatenate_files([atom() | binary() | [atom() | [any()] | char()]]) -> binary().
concatenate_files(Sources) ->
concatenate([read(Source) || Source <- Sources]).
View
9 src/rebar_js_handlebars_plugin.erl
@@ -76,10 +76,14 @@
-export([handlebars/4]).
+-type config() :: [{atom(), string()|list(string())}].
@cmeiklejohn Collaborator

Same here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
%% ===================================================================
%% Public API
%% ===================================================================
+-spec compile(config(), _) ->
+ ok.
compile(Config, _AppFile) ->
Options = options(Config),
OutDir = option(out_dir, Options),
@@ -89,6 +93,8 @@ compile(Config, _AppFile) ->
normalize_paths(Sources, DocRoot), Options} || {Destination, Sources} <- Templates],
build_each(Targets).
+-spec clean(config(), _) ->
+ ok.
clean(Config, _AppFile) ->
Options = options(Config),
OutDir = option(out_dir, Options),
@@ -96,8 +102,9 @@ clean(Config, _AppFile) ->
Targets = [normalize_path(Destination, OutDir) || {Destination, _} <- Templates],
delete_each(Targets).
-%% @spec handlebars(list(), list(), list(), list()) -> binary()
%% @doc Generate a handlebars compiler line.
+-spec handlebars(list(), list(), list(), list()) ->
+ binary().
handlebars(Name, Body, Target, Compiler) ->
Targeted = lists:flatten([Target, "['" ++ ensure_list(Name) ++ "']"]),
Compiled = lists:flatten([Compiler, "('" ++ ensure_list(Body) ++ "');\n"]),
View
8 src/rebar_js_stylus_plugin.erl
@@ -61,11 +61,14 @@
-export([compile/2,
clean/2]).
+-type config() :: [{atom(), string()|list(string())}].
@cmeiklejohn Collaborator

And here. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
%% ===================================================================
%% Public API
%% ===================================================================
-
+-spec compile(config(), any()) ->
+ any().
compile(Config, _AppFile) ->
Options = options(Config),
DocRoot = option(doc_root, Options),
@@ -101,9 +104,10 @@ process(Targets, Options) ->
ok
end.
+-spec clean(any(), any()) ->
+ ok.
clean(_Config, _AppFile) ->
ok.
-
%% ===================================================================
%% Internal functions
%% ===================================================================
View
4 src/riak_control_app.erl
@@ -28,9 +28,11 @@
%% ===================================================================
%% Application callbacks
%% ===================================================================
-
+-spec start(any(), any()) ->
+ {'error',_} | {'ok',pid()} | {'ok',pid(),_}.
start(_StartType, _StartArgs) ->
riak_control_sup:start_link().
+-spec stop(any()) -> ok.
stop(_State) ->
ok.
View
10 src/riak_control_formatting.erl
@@ -25,7 +25,15 @@
-include("riak_control.hrl").
+-record(ctx, {
+ base_url,
+ base_path
+ }).
+-type context() :: #ctx{}.
+
%% all actions return the same format
+-spec action_result({badrpc, any()}, wrq:reqdata(), context()) ->
+ {boolean(), wrq:reqdata(), context()}.
action_result(Error={badrpc,_},Req,C) ->
Body = mochijson2:encode({struct,[Error]}),
{false, wrq:set_resp_body(Body, Req), C};
@@ -37,6 +45,8 @@ action_result(_,Req,C) ->
{true, wrq:set_resp_body(Body, Req), C}.
%% return a proplist of details for a given index
+-spec node_ring_details(#partition_info{}, maybe_improper_list()) ->
+ [{'i' | 'index' | 'node' | 'reachable' | 'status' | [any(),...],atom() | binary() | integer()}].
node_ring_details (P=#partition_info{index=Index,vnodes=Vnodes},Nodes) ->
case lists:keyfind(P#partition_info.owner,2,Nodes) of
#member_info{node=Node,status=Status,reachable=Reachable} ->
View
8 src/riak_control_rpc.erl
@@ -25,11 +25,19 @@
-include("riak_control.hrl").
+-record(ctx, {
+ base_url,
+ base_path
+ }).
+-type context() :: #ctx{}.
+
%% get the target node for the action
target_node(Req) ->
list_to_existing_atom(dict:fetch(node,wrq:path_info(Req))).
%% remote to the target node, perform the action, and return
+-spec perform_rpc_action(wrq:reqdata(), context(), atom(), function(), list(any())) ->
+ {boolean(), wrq:reqdata(), context()}.
perform_rpc_action(Req,C,Module,Fun,Args) ->
Node=target_node(Req),
Result=case rpc:call(Node,Module,Fun,Args) of
View
10 src/riak_control_security.erl
@@ -37,6 +37,8 @@
%% if riak_control has an auth scheme selected, then we enforce
%% use of HTTPS and will redirect the user to the HTTPS version
%% of the page requested
+-spec scheme_is_available(wrq:reqdata(), context()) ->
+ {boolean() | {halt, non_neg_integer()}, wrq:reqdata(), context()}.
scheme_is_available(RD, Ctx) ->
case app_helper:get_env(riak_control, auth, none) of
none ->
@@ -51,6 +53,8 @@ scheme_is_available(RD, Ctx) ->
end.
%% get the https location to redirect to (callable w/o a request)
+-spec https_redirect_loc(string()) ->
+ {ok, string()} | undefined.
https_redirect_loc(Path) ->
case app_helper:get_env(riak_control, enabled, false) of
true ->
@@ -65,6 +69,8 @@ https_redirect_loc(Path) ->
end.
%% set the redirect header and where to go with it
+-spec https_redirect(wrq:reqdata(), context()) ->
+ {{halt, non_neg_integer()}, wrq:reqdata(), context()}.
https_redirect(RD,Ctx) ->
Path=wrq:raw_path(RD),
Loc=case https_redirect_loc(Path) of
@@ -92,6 +98,8 @@ https_redirect(RD,Ctx) ->
%%
%% - `none' :: No authentication.
%%
+-spec enforce_auth(wrq:reqdata(), context()) ->
+ {true | string(), wrq:reqdata(), context()}.
enforce_auth(RD, Ctx) ->
case app_helper:get_env(riak_control,auth,none) of
none ->
@@ -114,6 +122,8 @@ enforce_basic_auth(RD, Ctx, Base64, Auth) ->
{?ADMIN_AUTH_HEAD, RD, Ctx}
end.
+-spec enforce_user_pass(wrq:reqdata(), context(), string(), string(), string()) ->
+ {boolean(), wrq:reqdata(), context()}.
enforce_user_pass(RD, Ctx, User, Pass, Auth) ->
case valid_userpass(User, Pass, Auth) of
true ->
View
19 src/riak_control_session.erl
@@ -61,6 +61,7 @@
nodes :: members(),
update_tick :: boolean()}).
+-type state() :: #state{}.
-type normalized_action() :: leave | remove | replace | force_replace.
%% @doc Periodically update the ring with itself
@@ -140,6 +141,8 @@ force_update() ->
%% ring and membership changes.
%%
%% @end
+-spec init(list()) ->
+ {ok, state()}.
init([]) ->
%% make sure terminate/2 is called when the process exits
process_flag(trap_exit,true),
@@ -165,6 +168,8 @@ init([]) ->
%% start the server
{ok, update_ring(State, Ring)}.
+-spec handle_call(commit_plan, any(), state()) ->
+ {reply, any(), state()}.
handle_call(commit_plan, _From, State) ->
{reply, maybe_commit_plan(), State};
handle_call({stage_change, Node, Action, Replacement}, _From, State) ->
@@ -194,6 +199,9 @@ handle_call(get_partitions, _From, State=#state{vsn=V,partitions=P}) ->
%% update the ring any more until it's cleared.
%%
%% @end
+-spec handle_cast('update_ring' | {'update_ring',_} |
+ {'update_services',[{atom(),'fallback' | 'primary' | 'undefined'}]}, state()) ->
+ {'noreply',state()}.
handle_cast({update_ring, Ring}, State=#state{update_tick=Tick}) ->
case Tick of
false -> {noreply,update_ring(State,Ring)};
@@ -205,20 +213,23 @@ handle_cast(update_ring,State) ->
handle_cast({update_services, Services}, State) ->
{noreply, update_services(State, Services)}.
+-spec handle_info(ping_ring_nodes|clear_update_tick|_,state()) ->
+ {noreply, state()}.
handle_info(ping_ring_nodes, State) ->
erlang:send_after(?INTERVAL, self(), ping_ring_nodes),
{ok, Ring}=riak_core_ring_manager:get_my_ring(),
handle_cast({update_ring, Ring}, State);
-
handle_info(clear_update_tick, State) ->
{noreply, State#state{update_tick=false}};
handle_info(_,State) ->
{noreply, State}.
+-spec terminate(any(), any()) -> ok.
terminate (_Reason,_State) ->
ok.
-code_change (_Old,State,_Extra) ->
+-spec code_change(any(), state(), any()) -> {ok, state()}.
+code_change(_Old,State,_Extra) ->
{ok,State}.
%% ===================================================================
@@ -321,7 +332,7 @@ get_my_info() ->
handoffs = get_handoff_status()}.
%% @doc Return current nodes memory.
--spec get_my_memory() -> {term(), term()}.
+-spec get_my_memory() -> {number(), number()}.
get_my_memory() ->
Mem = memsup:get_system_memory_data(),
@@ -376,7 +387,7 @@ get_partition_details(#state{services=Services, ring=Ring}, {Idx, Owner}, HS) ->
handoffs = Handoffs}.
%% @doc Given a partition index, return.
--spec partition_index(ring(), integer()) -> term().
+-spec partition_index(ring(), integer()) -> integer().
partition_index(Ring, Index) ->
NumPartitions = riak_core_ring:num_partitions(Ring),
Index div chash:ring_increment(NumPartitions).
View
4 src/riak_control_sup.erl
@@ -35,13 +35,15 @@
%% API functions
%% ===================================================================
+-spec start_link() -> {ok, Pid::pid()} | ignore | {error, Error::any()}.
start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
%% ===================================================================
%% Supervisor callbacks
%% ===================================================================
-
+-spec init(list()) ->
+ {ok, {{'one_for_one', non_neg_integer(), non_neg_integer()}, [{_,{atom() | tuple(),atom(),'undefined' | [any()]},'permanent' | 'temporary' | 'transient','brutal_kill' | 'infinity' | non_neg_integer(),'supervisor' | 'worker','dynamic' | [atom() | tuple()]}]}}.
init([]) ->
RiakControlSession={riak_control_session,
{riak_control_session, start_link, []},
Something went wrong with that request. Please try again.