Raft is a distributed consensus algorithm. Consensus algorithms provide strong consistency guarantees to a cluster of servers, coordinating agreement on a value or safely replicating a state machine. Raft is mostly-equivalent to an earlier algorithm called Paxos, but was designed specifically to be easier to understand and leave less as an "exercise for the reader." You can read the original paper for an excellent description of the algorithm and its many uses. You can also read any Paxos paper to see why an easier and more exaustively-specified algorithm was necessary.
This repo contains my own implementation of Raft, in Haskell. I've implemented the full protocol, the two big pieces being log-entry propagation and leader election. Performance was not my focus, but it's fast enough to be IO-bound (and constrained by the configurable heartbeat/election timers) rather than CPU-bound. I also skipped space optimizations like log compaction, since I'm not using this in production anywhere and the log files take a long time to get huge.
Installing haskell is a huge pain for no reason, so if you don't have it I'd recommend just downloading the repo with precompiled binaries from the GitHub release page. If you just want to run the whole thing and see what's going on, here's how to do that:
# run the default cluster in three terminal tabs. # when a prompt pops up in one of them, type numbers in to submit log entries. ./raft-osx 1 ./raft-osx 2 ./raft-osx 3 # to see what's going on under the hood, open 3 more terminal tabs: tail -100f log/debug.1.log tail -100f log/debug.2.log tail -100f log/debug.3.log
It'll look like the picture above.
Here's the full usage information:
./raft-osx SERVER_ID [COMMAND] # commands = [log, test, leader, candidate, follower] ./raft-linux SERVER_ID [COMMAND] # commands = [log, test, leader, candidate, follower] Examples: ./raft-osx 1 # runs a Raft instance with ID=1 ./raft-osx 3 candidate # runs a Raft instance with ID=3, forcing it into a particular starting role (candidate) ./raft-osx 2 log # dumps a nicely-formatted version of Server 2's write-ahead log, found in db/log.ID.json. ./raft-osx 1 test # runs the tests for Server 1. The test harness has been set up, but there aren't many tests.
The config file,
conf/config.json, sets up a 3-node cluster to run locally. You can manually edit the JSON to change this, if you like.
ToyBoat compiles and runs on OSX and Linux. The repo includes a Rakefile for simplifying the compilation commands as well as managing Docker if you're on OSX but want the Linux version.
You need Ruby and Rake to build the project. Maybe someday I'll learn to enjoy writing Makefiles, but for now, google
installing RVM on [MY OS].
You need Haskell too (obviously). Installing it is hard but Google-able. The project uses GHC version 7.10. Once you have Haskell,
cabal build will install the project's dependencies.
Finally, you're ready to actually compile the damn project. Assuming you're running OSX
rake compile will compile for OSX, and
rake docker:build; rake docker:compile will compile for Linux using Docker.
Full list of Rakefile commands, for convenience:
rake # default: compile for both OSX and Linux rake reset # reset the state machine, clear the write-ahead logs rake log[ID] # dump the server log for server #ID; alias for ./raft-OS ID log rake debug[ID] # tail the log file for server #ID rake compile # compile for OSX rake run[ID] # run server #ID; alias for ./raft-OS ID rake docker:build # build a linux image with Haskell and Raft's dependencies rake docker:compile # compile for Linux using docker rake docker:run[ID] # run server #ID on Linux inside docker
if you're messing around with Docker you'll probably have to edit the Rakefile; there are a few Docker commands that insist on absolute paths.
Browse and act on your My Tasks list without leaving Emacs!
You'll need these packages, available from melpa via
Add this to your
.bash_profile (or wherever you keep your environment):
# Get a Personal Access Token from the `apps' tab in your app.asana.com profile settings. export ASANA_TOKEN="<my-asana-personal-access-token>"
Add this to your
;; or, if you prefer, use it in specific major modes:
;; (add-hook 'org-mode-hook 'asana-mode)
;; (add-hook 'prog-mode-hook 'asana-mode)
;; (add-hook 'text-mode-hook 'asana-mode)
[Optional] The default prefix for
asana-mode commands is
C-c a. To change it, add this to your
(setq asana-keymap-prefix "C-c C-a") ; Or whatever you'd like to use as your prefix
asana-mode minor mode, the following interactive commands are available:
helm-asana [C-c a a] helm-asana-change-workspace [C-c a A] asana-create-task-quickly [C-c a c] asana-create-task [C-c a C]
helm-asana task list provides these actions:
Select (view task details in buffer) [RET]
Browse (open in Asana) [C-b]
Move to section [C-:]
Move all marked tasks to section [M-:]
Complete all marked tasks [M-RET]
Delete all marked tasks [M-DEL]
OSX El Capitan can break
exec-path-from-shell, which corrupts your access token as it gets imported into Emacs. See https://github.com/purcell/exec-path-from-shell/issues/41 for more details. One available workaround is to disable OSX bash sessions with
Make Pinboard (http://pinboard.in) pins act more like browser bookmarks. Includes fuzzy search by pin title and url. Click the button or use a keyboard shortcut (suggested: Cmd-Shift-P or Ctrl-Shift-P) to bring up your Pinboard bookmarks. Search for tag names to filter, or search for a page title or URL to find a specific bookmark.
The results update as you type. Once you've found your bookmark, press Enter or Tab to open it. Hold Cmd (Mac) or Ctrl (Windows) to open it in a new tab.
I built this while putting off choosing classes. It helps you choose classes.
Axis & Allies is a tabletop minatures game I played a lot as a kid. This is my HTML5 tribute to that game: it's animated, multiplayer, completely free, and (I think) a lot of fun, so give it a try! This is probably my largest solo project.
Axis and Allies is a turn-based strategy game for two players. The game is played in rounds, and each round has several phases. At the start of each round, one player is chosen randomly to play first during each phase of that round.
My first major, finished(ish) personal project. Pumped!
I got to play around with APIs, somewhat-complex jQuery, and deal with building a full rails app from start to finish.
I also actually use this to keep track of all the TV shows I [never have time to] watch --and I hope that someone else will too. That'd be exciting.
I wanted the links to be very short but still look random, so they're not really very random. Links are 3 characters, and must include at least one letter and at least one number. They're case insensitive, so you can read them over the phone or something.
A little daemon that uses Twilio and Mailgun to intercept SMS messages and forward them to other phone numbers and email addresses. Use it to make Stanford 2Factor authentication less of a hassle!
(Read the effing article! Form your own opinions!)
A simple chrome extension that hides comment threads on news aggregator sites (currently HackerNews and Reddit) until after you've read the article.
On these sites I have an unfortunate habit of going to the comments to get the "gist" and then skipping the article entirely. I'm trying to break this habit... and spend less time in comment sections in general.
And I wanted to try building a chrome extension. (It was fun. B+!)
As it turns out, for security reasons you can't actually use js to determine whether a user has visited a link. So this extension manually keeps track of your last few hundred pages visited from HN/Reddit. In practice this works well enough.
Get it from the Google webstore.