#!/usr/bin/env ruby
# coding: utf-8
require 'rubygems'
require 'bundler/setup'
Bundler.require(:doc)
require 'yaml'
output = "
\n"
output << <<-TAB.lines.map(&:strip).join
Adapter | Required gems |
MRI support1 |
JRuby support1 |
Multi-thread safe2 |
Multi-process safe3 |
Atomic increment4 |
Atomic create5 |
Native expires6 |
Persistent |
Key Traversal |
Bulk read7 |
Bulk write8 |
Description |
TAB
output << "\n\n"
footnotes = {
"platform" => <<-EOF,
Indicates that the adapter is expected to work on this platform. Most adapters will at least
work on MRI, but some are curently considered unstable, in which case they are not supported
on any platform.
EOF
"multi-thread safe" => <<-EOF,
Make adapters thread-safe by using `Moneta::Lock` or by passing the option `threadsafe: true` to
`Moneta#new`. There is also `Moneta::Pool` which can be used to share a store between multiple
threads if the store is multi-process safe. I recommend to add the option `:threadsafe` to
ensure thread-safety since for example under JRuby and Rubinius even the basic datastructures
are not thread safe due to the lack of a global interpreter lock (GIL). This differs from MRI
where some adapters might appear thread safe already but only due to the GIL.
EOF
"multi-process safe" => <<-EOF,
Share a Moneta store between multiple processes using `Moneta::Shared` (See below).
EOF
"atomic increment" => <<-EOF,
If a store provides atomic increment it can be used with `Moneta::Semaphore`. You can add weak
`#increment` support using the `Moneta::WeakIncrement` proxy.
EOF
"atomic create" => <<-EOF,
If a store provides atomic creation it can be used with `Moneta::Mutex`. You can add weak
`#create` support using the `Moneta::WeakCreate` proxy.
EOF
"native expires" => <<-EOF,
Add expiration support by using `Moneta::Expires` or by passing the option `expires: true` to
`Moneta#new`.
EOF
"bulk read" => <<-EOF,
This indicates that there is some performance gain when fetching
multiple values at once using `#values_at`/`#fetch_values` or `#slice`.
For instance, the `MGET` instruction in Redis, or the ability to retrieve
several rows in one query in SQL.
EOF
"bulk write" => <<-EOF
This indicates that there is some performance gain when storing multiple
key/value pairs at once using `#merge!`/`#update`.
EOF
}
YAML.parse_stream(File.read(File.join(File.dirname(File.dirname(__FILE__)), 'feature_matrix.yaml'))) do |document|
feature_group = document.to_ruby
output << %{#{feature_group['group']} | |
\n\n}
feature_group['notes'].each do |k,v|
footnotes[k] = v
end
feature_group['backends'].each do |backend|
output << ''
output << "#{backend['adapter']} | "
output << "#{backend['gems'] || '-'} | "
features = backend['features'] | (feature_group['features'] || [])
features += backend['platforms'] || []
%w{MRI JRuby threadsafe multiprocess increment create expires persist each_key bulk_read bulk_write}.each do |feature|
supported = if features.include? feature
"yes"
elsif backend['unknown'] && backend['unknown'].include?(feature)
"unknown"
else
"no"
end
note = if backend['notes'] && backend['notes'][feature]
"#{footnotes.keys.index(backend['notes'][feature]) + 1}"
else
''
end
mark = case supported
when "yes"
"✓"
when "no"
"✗"
when "unknown"
'?'
end
colour = case supported
when "yes"
'#5F5'
when "no"
'#F44'
when "unknown"
'#55F'
end
output << %{#{mark}#{note} | }
end
html_description = if backend['description']
Kramdown::Document.new(backend['description']).to_html.match('(.*)
')[1]
else
''
end
output << "#{html_description} | "
output << '
'
output << "\n\n"
end
end
output << "
\n\n"
footnotes.each_value.each_with_index do |note, idx|
output << "#{idx+1}. #{note.lines.map(&:strip).join(" ")}\n"
end
readme = File.open('README.md', 'r+')
new_readme = readme.read.sub(/(name="backend-matrix".*?\n).*?(------)/m, "\\1\n#{output}\n\\2")
readme.rewind
readme << new_readme
readme.truncate(readme.tell)