rainbows 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }