Skip to content

Instantly share code, notes, and snippets.

View vladfaust's full-sized avatar
🕉️
एकक्षण

Vlad Faust vladfaust

🕉️
एकक्षण
View GitHub Profile
@vladfaust
vladfaust / sorbet-sum.rb
Created May 3, 2019 17:37
Sorbet is cool, but polished Crystal is better
# typed: true
require 'sorbet-runtime'
class A
extend T::Sig
sig {params(a: Integer, b: Integer).returns(Integer)}
def sum(a, b)
a + b
@vladfaust
vladfaust / sum.rb
Created May 3, 2019 17:36
Sorbet is cool, but polished Crystal is better
def sum(a, b)
# a and b could be anything. The interpreter must firstly find out their
# exact types and then decide what to do — to either sum numbers or strings
# or even raise if there is no "+" method for given types
a + b
end
@vladfaust
vladfaust / crystal-hello.cr
Created May 3, 2019 17:33
Sorbet is cool, but polished Crystal is better
def hello(who)
puts "Hello, #{who}!"
end
hello("world") # puts "Hello, world!"
@vladfaust
vladfaust / zmpopmax.lua
Created April 26, 2019 08:30
Redis scripts
-- Like ZPOPMAX but accept multiple keys and return a single member with maximum score across all the sets.
-- Returns array consisting of the key, member and its score; or nil if all sorted sets are empty.
--
-- EVAL ZMPOPMAX 2 keyA keyB
-- > "keyB"
-- > "foo"
-- > "1.5"
local max_member, max_score, max_key = nil, -math.inf, nil
local member, score = nil, nil

Scaling your API with rate limiters

The following are examples of the four types rate limiters discussed in the accompanying blog post. In the examples below I've used pseudocode-like Ruby, so if you're unfamiliar with Ruby you should be able to easily translate this approach to other languages. Complete examples in Ruby are also provided later in this gist.

In most cases you'll want all these examples to be classes, but I've used simple functions here to keep the code samples brief.

Request rate limiter

This uses a basic token bucket algorithm and relies on the fact that Redis scripts execute atomically. No other operations can run between fetching the count and writing the new count.

@vladfaust
vladfaust / timeout.cr
Created March 26, 2019 11:37
Crystal timeout
ch1 = Channel(Nil).new
ch2 = Channel(Nil).new
class Timeout
def self.new_select_action(span : Time::Span)
ch = Channel(Nil).new(1)
spawn do
sleep(span)
ch.send(nil)
@vladfaust
vladfaust / server_postgres.cr
Last active February 21, 2019 12:14
TechEmpower/FrameworkBenchmarks code for Onyx::REST
require "pg"
require "onyx/sql"
require "onyx/rest"
class World
include Onyx::SQL::Model
schema worlds do
pkey id : Int32
type random_number : Int32, key: "randomnumber"
@vladfaust
vladfaust / x.cr
Created January 20, 2019 16:11
Get all ancestors and descendants including modules in Crystal
# https://carc.in/#/r/620u
module Foo
end
module Bar
include Foo
end
class Baz
@vladfaust
vladfaust / pipeline.yml
Created January 10, 2019 09:29
Buildkite Crystal pipeline
steps:
- command:
- "shards install"
- "tar pczf lib.tar.gz lib/"
label: "Install shards"
artifact_paths: "lib.tar.gz"
plugins:
- docker#v2.1.0:
image: "crystallang/crystal:latest"
always-pull: true
@vladfaust
vladfaust / consumer.cr
Last active January 3, 2019 13:14
Onyx::EDA demo
require "../src/onyx-eda/channels/redis"
require "./events"
channel = Onyx::EDA::Channels::Redis.new
channel.subscribe(Events::User) do |event|
puts "[#{Time.now.to_s("%T:%6N")}] Got a user event, user_id = #{event.user_id}"
end
greeter = ->(event : Events::Users::Created) do