rainbows 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. data/.document +6 -5
  2. data/DEPLOY +13 -0
  3. data/GIT-VERSION-GEN +1 -1
  4. data/GNUmakefile +1 -1
  5. data/README +32 -6
  6. data/SIGNALS +11 -7
  7. data/TODO +2 -3
  8. data/lib/rainbows.rb +10 -3
  9. data/lib/rainbows/app_pool.rb +90 -0
  10. data/lib/rainbows/base.rb +41 -4
  11. data/lib/rainbows/const.rb +1 -6
  12. data/lib/rainbows/http_server.rb +1 -1
  13. data/lib/rainbows/rev.rb +174 -0
  14. data/lib/rainbows/revactor.rb +40 -37
  15. data/lib/rainbows/thread_pool.rb +31 -57
  16. data/lib/rainbows/thread_spawn.rb +32 -45
  17. data/local.mk.sample +4 -3
  18. data/t/.gitignore +1 -2
  19. data/t/GNUmakefile +21 -7
  20. data/t/README +42 -0
  21. data/t/bin/content-md5-put +36 -0
  22. data/t/bin/unused_listen +1 -1
  23. data/t/content-md5.ru +23 -0
  24. data/t/sleep.ru +11 -0
  25. data/t/t0000-basic.sh +29 -3
  26. data/t/t1000-thread-pool-basic.sh +5 -6
  27. data/t/t1000.ru +5 -1
  28. data/t/t1002-thread-pool-graceful.sh +37 -0
  29. data/t/t2000-thread-spawn-basic.sh +4 -6
  30. data/t/t2000.ru +5 -1
  31. data/t/t2002-thread-spawn-graceful.sh +37 -0
  32. data/t/t3000-revactor-basic.sh +4 -6
  33. data/t/t3000.ru +5 -1
  34. data/t/t3001-revactor-pipeline.sh +46 -0
  35. data/t/t3002-revactor-graceful.sh +38 -0
  36. data/t/t3003-revactor-reopen-logs.sh +54 -0
  37. data/t/t3100-revactor-tee-input.sh +8 -13
  38. data/t/t4000-rev-basic.sh +51 -0
  39. data/t/t4000.ru +9 -0
  40. data/t/t4002-rev-graceful.sh +52 -0
  41. data/t/t4003-rev-parser-error.sh +34 -0
  42. data/t/t4100-rev-rack-input.sh +44 -0
  43. data/t/t4101-rev-rack-input-trailer.sh +51 -0
  44. data/t/t9000-rack-app-pool.sh +37 -0
  45. data/t/t9000.ru +14 -0
  46. data/t/test-lib.sh +29 -2
  47. data/vs_Unicorn +50 -1
  48. metadata +28 -6
@@ -0,0 +1,54 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ require_revactor
4
+
5
+ eval $(unused_listen)
6
+ rtmpfiles unicorn_config curl_out curl_err pid r_err r_out r_rot
7
+
8
+ nr_client=30
9
+ nr_actor=10
10
+
11
+ cat > $unicorn_config <<EOF
12
+ listen "$listen"
13
+ pid "$pid"
14
+ stderr_path "$r_err"
15
+ stdout_path "$r_out"
16
+ Rainbows! do
17
+ use :Revactor
18
+ worker_connections $nr_actor
19
+ end
20
+ EOF
21
+
22
+ SLEEP_CLASS=Actor rainbows -D sleep.ru -c $unicorn_config
23
+ wait_for_pid $pid
24
+
25
+ start=$(date +%s)
26
+ for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
27
+ do
28
+ ( curl -sSf http://$listen/2 >> $curl_out 2>> $curl_err ) &
29
+ done
30
+ ! grep Error $r_err
31
+
32
+ rm $r_rot
33
+ mv $r_err $r_rot
34
+
35
+ kill -USR1 $(cat $pid)
36
+ wait_for_pid $r_err
37
+
38
+ dbgcat r_rot
39
+ dbgcat r_err
40
+
41
+ wait
42
+ echo elapsed=$(( $(date +%s) - $start ))
43
+ ! test -s $curl_err
44
+ test x"$(wc -l < $curl_out)" = x$nr_client
45
+ nr=$(sort < $curl_out | uniq | wc -l)
46
+
47
+ test "$nr" -eq 1
48
+ test x$(sort < $curl_out | uniq) = xHello
49
+ ! grep Error $r_err
50
+ ! grep Error $r_rot
51
+
52
+ kill $(cat $pid)
53
+ dbgcat r_err
54
+ ! grep Error $r_err
@@ -4,17 +4,10 @@ nr_actor=${nr_actor-50}
4
4
 
5
5
  . ./test-lib.sh
6
6
  require_revactor
7
+ test -r random_blob || die "random_blob required, run with 'make $0'"
7
8
 
8
9
  eval $(unused_listen)
9
- unicorn_config=$(mktemp -t rainbows.$$.unicorn.rb.XXXXXXXX)
10
- curl_out=$(mktemp -t rainbows.$$.curl.out.XXXXXXXX)
11
- curl_err=$(mktemp -t rainbows.$$.curl.err.XXXXXXXX)
12
- r_err=$(mktemp -t rainbows.$$.r.err.XXXXXXXX)
13
- r_out=$(mktemp -t rainbows.$$.r.out.XXXXXXXX)
14
- pid=$(mktemp -t rainbows.$$.pid.XXXXXXXX)
15
- blob=$(mktemp -t rainbows.$$.blob.XXXXXXXX)
16
- TEST_RM_LIST="$TEST_RM_LIST $unicorn_config $lock_path $r_err $r_out"
17
- TEST_RM_LIST="$TEST_RM_LIST $curl_out $curl_err $blob $pid"
10
+ rtmpfiles unicorn_config curl_out curl_err r_err r_out pid
18
11
 
19
12
  cat > $unicorn_config <<EOF
20
13
  listen "$listen"
@@ -31,12 +24,13 @@ echo pid=$pid
31
24
  rainbows -D sha1.ru -c $unicorn_config
32
25
  wait_for_pid $pid
33
26
 
34
- dd if=/dev/urandom bs=1M count=10 of=$blob 2>/dev/null
35
-
36
27
  start=$(date +%s)
37
28
  for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
38
29
  do
39
- ( curl -sSf -T- < $blob http://$listen/$i >> $curl_out 2>> $curl_err ) &
30
+ (
31
+ curl -sSf -T- http://$listen/$i \
32
+ < random_blob >> $curl_out 2>> $curl_err
33
+ ) &
40
34
  done
41
35
  wait
42
36
  echo elapsed=$(( $(date +%s) - $start ))
@@ -44,6 +38,7 @@ echo elapsed=$(( $(date +%s) - $start ))
44
38
  kill $(cat $pid)
45
39
  test $nr_client -eq $(wc -l < $curl_out)
46
40
  test 1 -eq $(sort < $curl_out | uniq | wc -l)
47
- blob_sha1=$( expr "$(sha1sum < $blob)" : '\([a-f0-9]\+\)')
41
+ blob_sha1=$( expr "$(sha1sum < random_blob)" : '\([a-f0-9]\+\)')
48
42
  echo blob_sha1=$blob_sha1
49
43
  test x"$blob_sha1" = x"$(sort < $curl_out | uniq)"
44
+ ! grep Error $r_err
@@ -0,0 +1,51 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ require_rev
4
+
5
+ eval $(unused_listen)
6
+ rtmpfiles unicorn_config pid r_err r_out tmp fifo ok
7
+ rm -f $fifo
8
+ mkfifo $fifo
9
+
10
+ nr_client=30
11
+
12
+ cat > $unicorn_config <<EOF
13
+ listen "$listen"
14
+ pid "$pid"
15
+ stderr_path "$r_err"
16
+ stdout_path "$r_out"
17
+ Rainbows! do
18
+ use :Rev
19
+ worker_connections 50
20
+ end
21
+ EOF
22
+
23
+ rainbows -D t4000.ru -c $unicorn_config
24
+ wait_for_pid $pid
25
+
26
+ echo "single request"
27
+ curl -sSfv http://$listen/
28
+
29
+ echo "two requests with keepalive"
30
+ curl -sSfv http://$listen/a http://$listen/b > $tmp 2>&1
31
+ grep 'Re-using existing connection' < $tmp
32
+
33
+ echo "pipelining partial requests"
34
+ req='GET / HTTP/1.1\r\nHost: example.com\r\n'
35
+ (
36
+ printf "$req"'\r\n'"$req"
37
+ cat $fifo > $tmp &
38
+ sleep 1
39
+ printf 'Connection: close\r\n\r\n'
40
+ wait
41
+ echo ok > $ok
42
+ ) | socat - TCP:$listen > $fifo
43
+
44
+ kill $(cat $pid)
45
+
46
+ test 2 -eq $(grep '^HTTP/1.1' $tmp | wc -l)
47
+ test 2 -eq $(grep '^HTTP/1.1 200 OK' $tmp | wc -l)
48
+ test 1 -eq $(grep '^Connection: keep-alive' $tmp | wc -l)
49
+ test 1 -eq $(grep '^Connection: close' $tmp | wc -l)
50
+ test x"$(cat $ok)" = xok
51
+ ! grep Error $r_err
data/t/t4000.ru ADDED
@@ -0,0 +1,9 @@
1
+ use Rack::ContentLength
2
+ use Rack::ContentType
3
+ run lambda { |env|
4
+ if env['rack.multithread'] == false && env['rainbows.model'] == :Rev
5
+ [ 200, {}, [ env.inspect << "\n" ] ]
6
+ else
7
+ raise "rack.multithread is true"
8
+ end
9
+ }
@@ -0,0 +1,52 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ require_rev
4
+
5
+ eval $(unused_listen)
6
+ rtmpfiles unicorn_config tmp pid r_err r_out out
7
+ nr_client=10
8
+ cat > $unicorn_config <<EOF
9
+ listen "$listen"
10
+ stderr_path "$r_err"
11
+ stdout_path "$r_out"
12
+ pid "$pid"
13
+ Rainbows! do
14
+ use :Rev
15
+ end
16
+ EOF
17
+
18
+ rainbows -D sleep.ru -c $unicorn_config
19
+ wait_for_pid $pid
20
+
21
+ for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
22
+ do
23
+ (
24
+ rtmpfiles fifo tmp
25
+ rm -f $fifo
26
+ mkfifo $fifo
27
+ (
28
+ printf 'GET /0 HTTP/1.1\r\n'
29
+ cat $fifo > $tmp &
30
+ sleep 1
31
+ printf 'Host: example.com\r\n'
32
+ sleep 1
33
+ printf 'Connection: close\r\n'
34
+ sleep 1
35
+ printf '\r\n'
36
+ wait
37
+ ) | socat - TCP:$listen > $fifo
38
+ fgrep 'Hello' $tmp >> $out || :
39
+ rm -f $fifo $tmp
40
+ ) &
41
+ done
42
+
43
+ sleep 2 # potentially racy :<
44
+ kill -QUIT $(cat $pid)
45
+ wait
46
+
47
+ test x"$(wc -l < $out)" = x$nr_client
48
+ nr=$(sort < $out | uniq | wc -l)
49
+ test "$nr" -eq 1
50
+
51
+ test x$(sort < $out | uniq) = xHello
52
+ ! grep Error $r_err
@@ -0,0 +1,34 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ require_rev
4
+
5
+ eval $(unused_listen)
6
+ rtmpfiles unicorn_config pid r_err r_out tmp fifo ok
7
+ rm -f $fifo
8
+ mkfifo $fifo
9
+
10
+ cat > $unicorn_config <<EOF
11
+ listen "$listen"
12
+ pid "$pid"
13
+ stderr_path "$r_err"
14
+ stdout_path "$r_out"
15
+ Rainbows! do
16
+ use :Rev
17
+ end
18
+ EOF
19
+
20
+ rainbows -D t4000.ru -c $unicorn_config
21
+ wait_for_pid $pid
22
+
23
+ (
24
+ printf 'GET / HTTP/1/1\r\nHost: example.com\r\n\r\n'
25
+ cat $fifo > $tmp &
26
+ wait
27
+ echo ok > $ok
28
+ ) | socat - TCP:$listen > $fifo
29
+
30
+ kill $(cat $pid)
31
+
32
+ dbgcat tmp
33
+ grep -F 'HTTP/1.1 400 Bad Request' $tmp
34
+ ! grep Error $r_err
@@ -0,0 +1,44 @@
1
+ #!/bin/sh
2
+ nr_client=${nr_client-25}
3
+ nr=${nr-50}
4
+
5
+ . ./test-lib.sh
6
+ require_rev
7
+ test -r random_blob || die "random_blob required, run with 'make $0'"
8
+
9
+ eval $(unused_listen)
10
+ rtmpfiles unicorn_config curl_out curl_err r_err r_out pid
11
+
12
+ cat > $unicorn_config <<EOF
13
+ listen "$listen"
14
+ pid "$pid"
15
+ stderr_path "$r_err"
16
+ stdout_path "$r_out"
17
+ Rainbows! do
18
+ use :Rev
19
+ worker_connections $nr
20
+ end
21
+ EOF
22
+
23
+ echo pid=$pid
24
+ rainbows -D sha1.ru -c $unicorn_config
25
+ wait_for_pid $pid
26
+
27
+ start=$(date +%s)
28
+ for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
29
+ do
30
+ (
31
+ curl -sSf -T- http://$listen/$i \
32
+ < random_blob >> $curl_out 2>> $curl_err
33
+ ) &
34
+ done
35
+ wait
36
+ echo elapsed=$(( $(date +%s) - $start ))
37
+
38
+ kill $(cat $pid)
39
+ test $nr_client -eq $(wc -l < $curl_out)
40
+ test 1 -eq $(sort < $curl_out | uniq | wc -l)
41
+ blob_sha1=$( expr "$(sha1sum < random_blob)" : '\([a-f0-9]\+\)')
42
+ echo blob_sha1=$blob_sha1
43
+ test x"$blob_sha1" = x"$(sort < $curl_out | uniq)"
44
+ ! grep Error $r_err
@@ -0,0 +1,51 @@
1
+ #!/bin/sh
2
+ nr_client=${nr_client-25}
3
+ nr=${nr-50}
4
+
5
+ . ./test-lib.sh
6
+ require_rev
7
+ test -r random_blob || die "random_blob required, run with 'make $0'"
8
+
9
+ eval $(unused_listen)
10
+ rtmpfiles unicorn_config tmp r_err r_out pid fifo ok
11
+ rm -f $fifo
12
+ mkfifo $fifo
13
+
14
+ cat > $unicorn_config <<EOF
15
+ listen "$listen"
16
+ pid "$pid"
17
+ stderr_path "$r_err"
18
+ stdout_path "$r_out"
19
+ Rainbows! do
20
+ use :Rev
21
+ end
22
+ EOF
23
+
24
+ rainbows -D content-md5.ru -c $unicorn_config
25
+ wait_for_pid $pid
26
+
27
+ echo "small blob"
28
+ (
29
+ echo hello world | content-md5-put
30
+ cat $fifo > $tmp &
31
+ wait
32
+ echo ok > $ok
33
+ ) | socat - TCP:$listen | tee $fifo
34
+
35
+ fgrep 'HTTP/1.1 200 OK' $tmp
36
+ test xok = x"$(cat $ok)"
37
+ ! grep Error $r_err
38
+
39
+
40
+ echo "big blob"
41
+ (
42
+ content-md5-put < random_blob
43
+ cat $fifo > $tmp &
44
+ wait
45
+ echo ok > $ok
46
+ ) | socat - TCP:$listen | tee $fifo
47
+
48
+ fgrep 'HTTP/1.1 200 OK' $tmp
49
+ test xok = x"$(cat $ok)"
50
+ ! grep Error $r_err
51
+ kill $(cat $pid)
@@ -0,0 +1,37 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+
4
+ eval $(unused_listen)
5
+ rtmpfiles unicorn_config pid r_err r_out curl_out curl_err
6
+
7
+ nr_client=30
8
+
9
+ cat > $unicorn_config <<EOF
10
+ listen "$listen"
11
+ pid "$pid"
12
+ stderr_path "$r_err"
13
+ stdout_path "$r_out"
14
+ Rainbows! do
15
+ use :ThreadSpawn
16
+ worker_connections 50
17
+ end
18
+ EOF
19
+
20
+ APP_POOL_SIZE=4
21
+ APP_POOL_SIZE=$APP_POOL_SIZE rainbows -D t9000.ru -c $unicorn_config
22
+ wait_for_pid $pid
23
+
24
+ start=$(date +%s)
25
+ for i in $(awk "BEGIN{for(i=0;i<$nr_client;++i) print i}" </dev/null)
26
+ do
27
+ ( curl -sSf http://$listen/ >> $curl_out 2>> $curl_err ) &
28
+ done
29
+ wait
30
+ echo elapsed=$(( $(date +%s) - $start ))
31
+ kill $(cat $pid)
32
+
33
+ test $APP_POOL_SIZE -eq $(sort < $curl_out | uniq | wc -l)
34
+ ! test -s $curl_err
35
+
36
+ ! grep Error $r_err
37
+ #
data/t/t9000.ru ADDED
@@ -0,0 +1,14 @@
1
+ use Rack::ContentLength
2
+ use Rack::ContentType
3
+ use Rainbows::AppPool, :size => ENV['APP_POOL_SIZE'].to_i
4
+ sleep_class = ENV['SLEEP_CLASS']
5
+ sleep_class = sleep_class ? Object.const_get(sleep_class) : Kernel
6
+ class Sleeper
7
+ def call(env)
8
+ sleep_class = ENV['SLEEP_CLASS']
9
+ sleep_class = sleep_class ? Object.const_get(sleep_class) : Kernel
10
+ sleep_class.sleep 1
11
+ [ 200, {}, [ "#{object_id}\n" ] ]
12
+ end
13
+ end
14
+ run Sleeper.new
data/t/test-lib.sh CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/bin/sh
2
2
  # Copyright (c) 2009 Rainbows! developers
3
+
4
+ set -o pipefail >/dev/null 2>&1 || : # non-POSIX, but useful in ksh/bash
3
5
  set -e
4
6
  set -u
5
7
  T=$(basename $0)
@@ -15,8 +17,8 @@ die () {
15
17
  exit 1
16
18
  }
17
19
 
18
- TEST_RM_LIST=""
19
- trap 'rm -f $TEST_RM_LIST' 0
20
+ _TEST_RM_LIST=""
21
+ trap 'rm -f $_TEST_RM_LIST' 0
20
22
  PATH=$PWD/bin:$PATH
21
23
  export PATH
22
24
 
@@ -39,3 +41,28 @@ require_revactor () {
39
41
  exit 0
40
42
  fi
41
43
  }
44
+
45
+ require_rev() {
46
+ if ! $ruby -rrev -e "puts Rev::VERSION" >/dev/null 2>&1
47
+ then
48
+ echo >&2 "skipping $T since we don't have Rev"
49
+ exit 0
50
+ fi
51
+ }
52
+
53
+ # given a list of variable names, create temporary files and assign
54
+ # the pathnames to those variables
55
+ rtmpfiles () {
56
+ for id in "$@"
57
+ do
58
+ _tmp=$(mktemp -t rainbows.$$.$id.XXXXXXXX)
59
+ eval "$id=$_tmp"
60
+ _TEST_RM_LIST="$_TEST_RM_LIST $_tmp"
61
+ done
62
+ }
63
+
64
+ dbgcat () {
65
+ id=$1
66
+ eval '_file=$'$id
67
+ sed -e "s/^/$id:/" < $_file
68
+ }