rimless 1.1.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/documentation.yml +39 -0
  3. data/.github/workflows/test.yml +63 -0
  4. data/.rspec +2 -2
  5. data/.rubocop.yml +16 -2
  6. data/.simplecov +12 -0
  7. data/Appraisals +2 -22
  8. data/CHANGELOG.md +12 -0
  9. data/Dockerfile +2 -3
  10. data/Envfile +0 -3
  11. data/Guardfile +44 -0
  12. data/LICENSE +1 -1
  13. data/Makefile +25 -15
  14. data/README.md +11 -4
  15. data/Rakefile +13 -65
  16. data/doc/kafka-playground/.gitignore +2 -0
  17. data/doc/kafka-playground/Dockerfile +41 -0
  18. data/doc/kafka-playground/Gemfile +8 -0
  19. data/doc/kafka-playground/Gemfile.lock +155 -0
  20. data/doc/kafka-playground/Makefile +209 -0
  21. data/doc/kafka-playground/README.md +185 -0
  22. data/doc/kafka-playground/bin/consume-topic +7 -0
  23. data/doc/kafka-playground/bin/create-topic +42 -0
  24. data/doc/kafka-playground/bin/delete-topic +22 -0
  25. data/doc/kafka-playground/bin/list-topics +3 -0
  26. data/doc/kafka-playground/bin/produce-event +64 -0
  27. data/doc/kafka-playground/config/avro_schemas/.gitignore +1 -0
  28. data/doc/kafka-playground/config/avro_schemas/playground_app/item_v1.avsc.erb +36 -0
  29. data/doc/kafka-playground/config/avro_schemas/playground_app/payment_v1.avsc.erb +59 -0
  30. data/doc/kafka-playground/config/avro_schemas/playground_app/payment_v1_event.avsc.erb +18 -0
  31. data/doc/kafka-playground/config/docker/shell/.bash_profile +3 -0
  32. data/doc/kafka-playground/config/docker/shell/.bashrc +231 -0
  33. data/doc/kafka-playground/config/docker/shell/.config/kcat.conf +3 -0
  34. data/doc/kafka-playground/config/docker/shell/.gemrc +2 -0
  35. data/doc/kafka-playground/config/docker/shell/.inputrc +17 -0
  36. data/doc/kafka-playground/config/environment.rb +69 -0
  37. data/doc/kafka-playground/doc/assets/project.svg +68 -0
  38. data/doc/kafka-playground/docker-compose.yml +83 -0
  39. data/doc/kafka-playground/examples/rimless-produce +48 -0
  40. data/gemfiles/rails_5.2.gemfile +2 -2
  41. data/lib/rimless/configuration_handling.rb +11 -1
  42. data/lib/rimless/consumer.rb +4 -2
  43. data/lib/rimless/dependencies.rb +3 -0
  44. data/lib/rimless/kafka_helpers.rb +2 -0
  45. data/lib/rimless/karafka/avro_deserializer.rb +3 -3
  46. data/lib/rimless/rspec/helpers.rb +11 -0
  47. data/lib/rimless/rspec/matchers.rb +24 -9
  48. data/lib/rimless/rspec.rb +1 -1
  49. data/lib/rimless/tasks/consumer.rake +3 -0
  50. data/lib/rimless/tasks/generator.rake +3 -0
  51. data/lib/rimless/tasks/stats.rake +5 -2
  52. data/lib/rimless/version.rb +18 -1
  53. data/lib/rimless.rb +0 -1
  54. data/rimless.gemspec +43 -29
  55. metadata +121 -71
  56. data/.travis.yml +0 -35
  57. data/gemfiles/rails_4.2.gemfile +0 -8
  58. data/gemfiles/rails_5.0.gemfile +0 -8
  59. data/gemfiles/rails_5.1.gemfile +0 -8
  60. data/gemfiles/rails_6.0.gemfile +0 -8
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "item_v1",
3
+ "doc": "Playground App - item attached to a payment",
4
+ "namespace": "<%= namespace %>",
5
+ "type": "record",
6
+ "fields": [
7
+ {
8
+ "name": "gid",
9
+ "type": "string",
10
+ "doc": "The global ID of the item that is being sold"
11
+ },
12
+ {
13
+ "name": "net_amount",
14
+ "type": "int",
15
+ "doc": "The price of the item in cents (without tax)"
16
+ },
17
+ {
18
+ "name": "tax_rate",
19
+ "type": "float",
20
+ "doc": "The tax rate for the item"
21
+ },
22
+ {
23
+ "name": "created_at",
24
+ "type": "string",
25
+ "doc": "When the user was created (ISO 8601)"
26
+ },
27
+ {
28
+ "name": "updated_at",
29
+ "type": [
30
+ "null",
31
+ "string"
32
+ ],
33
+ "doc": "When the item was last updated (ISO 8601)"
34
+ }
35
+ ]
36
+ }
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "payment_v1",
3
+ "doc": "Playground App - the payment",
4
+ "namespace": "<%= namespace %>",
5
+ "type": "record",
6
+ "fields": [
7
+ {
8
+ "name": "gid",
9
+ "type": "string",
10
+ "doc": "Global ID of the payment (UUID)"
11
+ },
12
+ {
13
+ "name": "currency",
14
+ "type": "string",
15
+ "doc": "The currency used for the payment"
16
+ },
17
+ {
18
+ "name": "net_amount_sum",
19
+ "type": "int",
20
+ "doc": "The price sum with tax included in cents"
21
+ },
22
+ {
23
+ "name": "items",
24
+ "type": {
25
+ "items": "<%= namespace %>.item_v1",
26
+ "type": "array"
27
+ },
28
+ "doc": "All connected payment items"
29
+ },
30
+ {
31
+ "name": "state",
32
+ "type": {
33
+ "name": "state",
34
+ "type": "enum",
35
+ "symbols": [
36
+ "pending",
37
+ "authorized",
38
+ "settled",
39
+ "cancelled",
40
+ "failed"
41
+ ]
42
+ },
43
+ "doc": "The current state of the payment"
44
+ },
45
+ {
46
+ "name": "created_at",
47
+ "type": "string",
48
+ "doc": "When the payment was created (ISO 8601)"
49
+ },
50
+ {
51
+ "name": "updated_at",
52
+ "type": [
53
+ "null",
54
+ "string"
55
+ ],
56
+ "doc": "When the payment was last updated (ISO 8601)"
57
+ }
58
+ ]
59
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "payment_v1_event",
3
+ "namespace": "<%= namespace %>",
4
+ "type": "record",
5
+ "doc": "Playground App - payment event representation",
6
+ "fields": [
7
+ {
8
+ "doc": "The event name/type",
9
+ "name": "event",
10
+ "type": "string"
11
+ },
12
+ {
13
+ "doc": "The corresponding payment of the event",
14
+ "name": "payment",
15
+ "type": "<%= namespace %>.payment_v1"
16
+ }
17
+ ]
18
+ }
@@ -0,0 +1,3 @@
1
+ if [ -f ~/.bashrc ]; then
2
+ . ~/.bashrc
3
+ fi
@@ -0,0 +1,231 @@
1
+ # ~/.bashrc: executed by bash(1) for non-login shells.
2
+ # see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
3
+ # for examples
4
+
5
+ _GEM_PATHS=$(ls -d1 ${HOME}/.gem/ruby/*/bin 2>/dev/null | paste -sd ':')
6
+ _APP_PATHS=$(ls -d1 /app/vendor/bundle/ruby/*/bin 2>/dev/null | paste -sd ':')
7
+
8
+ export PATH="${_GEM_PATHS}:${_APP_PATHS}:${PATH}"
9
+ export PATH="/app/node_modules/.bin:${HOME}/.bin:/app/bin:${PATH}"
10
+ export MAKE_ENV=baremetal
11
+
12
+ # Disable the autostart of all supervisord units
13
+ sudo sed -i 's/autostart=.*/autostart=false/g' /etc/supervisor/conf.d/*
14
+
15
+ # Start the supervisord (empty, no units)
16
+ sudo supervisord >/dev/null 2>&1 &
17
+
18
+ # Wait for supervisord
19
+ while ! supervisorctl status >/dev/null 2>&1; do sleep 1; done
20
+
21
+ # Boot the mDNS stack
22
+ echo '# Start the mDNS stack'
23
+ sudo supervisorctl start dbus avahi
24
+ echo
25
+
26
+ # Start the ssh-agent
27
+ echo '# Start the SSH agent'
28
+ eval "$(ssh-agent -s)" >/dev/null
29
+
30
+ # Run a user script for adding the relevant ssh keys
31
+ if [ -f ~/.ssh/add-all ]; then
32
+ . ~/.ssh/add-all
33
+ fi
34
+
35
+ # If not running interactively, don't do anything
36
+ case $- in
37
+ *i*) ;;
38
+ *) return;;
39
+ esac
40
+
41
+ # Clear the color for the first time
42
+ echo -e "\e[0m"
43
+
44
+ export HISTCONTROL="ignoreboth:erasedups"
45
+ export HISTSIZE=1000000
46
+
47
+ # Enable less mouse scrolling
48
+ export LESS=-r
49
+
50
+ # Default Editor
51
+ export EDITOR=vim
52
+
53
+ # set variable identifying the chroot you work in (used in the prompt below)
54
+ if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
55
+ debian_chroot=$(cat /etc/debian_chroot)
56
+ fi
57
+
58
+ # If this is an xterm set the title to user@host:dir
59
+ case "$TERM" in
60
+ xterm*|rxvt*)
61
+ PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
62
+ ;;
63
+ *)
64
+ ;;
65
+ esac
66
+
67
+ # enable color support of ls and also add handy aliases
68
+ if [ -x /usr/bin/dircolors ]; then
69
+ test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" \
70
+ || eval "$(dircolors -b)"
71
+ fi
72
+
73
+ if [ -f ~/.bash_aliases ]; then
74
+ . ~/.bash_aliases
75
+ fi
76
+
77
+ # enable programmable completion features (you don't need to enable
78
+ # this, if it's already enabled in /etc/bash.bashrc and /etc/profile
79
+ # sources /etc/bash.bashrc).
80
+ if ! shopt -oq posix; then
81
+ if [ -f /usr/share/bash-completion/bash_completion ]; then
82
+ . /usr/share/bash-completion/bash_completion
83
+ elif [ -f /etc/bash_completion ]; then
84
+ . /etc/bash_completion
85
+ fi
86
+ fi
87
+
88
+ export COLOR_OPTIONS='--color=auto'
89
+
90
+ alias ..="cd .."
91
+ alias ...="cd ../.."
92
+ alias ....="cd ../../.."
93
+ alias .....="cd ../../../.."
94
+ alias ls='ls $COLOR_OPTIONS --group-directories-first --time-style="+%F, %T "'
95
+ alias ll='ls $COLOR_OPTIONS -lh'
96
+ alias l='ls $COLOR_OPTIONS -lAh'
97
+ alias grep='grep $COLOR_OPTIONS'
98
+ alias egrep='egrep $COLOR_OPTIONS'
99
+ alias g='git'
100
+ alias p='pwd'
101
+ alias mkdir='mkdir -p -v'
102
+ alias less='less -R'
103
+ alias x='exit'
104
+ alias playground='ls -1 /app/bin | sed "s/^/* /g"'
105
+ alias pl='playground'
106
+
107
+ # Bash won't get SIGWINCH if another process is in the foreground.
108
+ # Enable checkwinsize so that bash will check the terminal size when
109
+ # it regains control. #65623
110
+ # http://cnswww.cns.cwru.edu/~chet/bash/FAQ (E11)
111
+ shopt -s checkwinsize
112
+
113
+ # Enable history appending instead of overwriting.
114
+ shopt -s histappend
115
+
116
+ # Enable extended globbing
117
+ shopt -s extglob
118
+
119
+ # Enable globbing for dotfiles
120
+ shopt -s dotglob
121
+
122
+ # Enable globstars for recursive globbing
123
+ shopt -s globstar
124
+
125
+ # Auto "cd" when entering just a path
126
+ shopt -s autocd
127
+
128
+ # Disable XOFF (interrupt data flow)
129
+ stty -ixoff
130
+
131
+ # Disable XON (interrupt data flow)
132
+ stty -ixon
133
+
134
+ bind "set completion-ignore-case on" # note: bind used instead of sticking these in .inputrc
135
+ bind "set bell-style none" # no bell
136
+ bind "set show-all-if-ambiguous On" # show list automatically, without double tab
137
+
138
+ # use ctl keys to move forward and back in words
139
+ bind '"\e[1;5C": forward-word'
140
+ bind '"\e[1;5D": backward-word'
141
+ bind '"\e[5C": forward-word'
142
+ bind '"\e[5D": backward-word'
143
+ bind '"\e\e[C": forward-word'
144
+ bind '"\e\e[D": backward-word'
145
+
146
+ # use arrow keys to fast search
147
+ bind '"\e[A": history-search-backward'
148
+ bind '"\e[B": history-search-forward'
149
+
150
+ # Enable colors for ls, etc. Prefer ~/.dir_colors #64489
151
+ if type -P dircolors >/dev/null ; then
152
+ if [[ -f ~/.dir_colors ]] ; then
153
+ eval $(dircolors -b ~/.dir_colors)
154
+ elif [[ -f /etc/DIR_COLORS ]] ; then
155
+ eval $(dircolors -b /etc/DIR_COLORS)
156
+ fi
157
+ fi
158
+
159
+ function watch-make-test()
160
+ {
161
+ while [ 1 ]; do
162
+ inotifywait --quiet -r `pwd` -e close_write --format '%e -> %w%f'
163
+ make test
164
+ done
165
+ }
166
+
167
+ function watch-make()
168
+ {
169
+ while [ 1 ]; do
170
+ inotifywait --quiet -r `pwd` -e close_write --format '%e -> %w%f'
171
+ make $@
172
+ done
173
+ }
174
+
175
+ function watch-run()
176
+ {
177
+ while [ 1 ]; do
178
+ inotifywait --quiet -r `pwd` -e close_write --format '%e -> %w%f'
179
+ bash -c "$@"
180
+ done
181
+ }
182
+
183
+ PROMPT_COMMAND='RET=$?;'
184
+ RET_OUT='$(if [[ $RET = 0 ]]; then echo -ne "\[\e[0;32m\][G]"; else echo -ne "\[\e[0;31m\][Err: $RET]"; fi;)'
185
+ RET_OUT="\n$RET_OUT"
186
+
187
+ HOST="${MDNS_HOSTNAME}"
188
+ if [ -z "${HOST}" ]; then
189
+ HOST="\h"
190
+ fi
191
+
192
+ _TIME='\t'
193
+ _FILES="\$(ls -a1 | grep -vE '\.$' | wc -l)"
194
+ _SIZE="\$(ls -lah | head -n1 | cut -d ' ' -f2)"
195
+ _META="${_TIME} | Files: ${_FILES} | Size: ${_SIZE} | \[\e[0;36m\]\w"
196
+ META=" \[\e[0;31m\][\[\e[1;37m\]${_META}\[\e[0;31m\]]\[\e[0;32m\]\033]2;\w\007"
197
+
198
+ PSL1=${RET_OUT}${META}
199
+ PSL2="\n\[\e[0;31m\][\u\[\e[0;33m\]@\[\e[0;37m\]${HOST}\[\e[0;31m\]] \[\e[0;31m\]$\[\e[0;32m\] "
200
+
201
+ export PS1=${PSL1}${PSL2}
202
+
203
+ clear
204
+ NORMAL=$(printf '\e[0m')
205
+ COLOR=$(printf '\e[1;34m')
206
+ R=$(printf '\e[0;31m')
207
+ B=$(printf '\e[0;34m')
208
+ Z=$(printf '\e[0m')
209
+ cat <<EOF
210
+ ##########
211
+ #
212
+ # ${R}++${Z}
213
+ # ${R}++++++${Z}
214
+ # ${R}++++++++${Z} ${B}_ _ _ _${Z}
215
+ # ${R}++++++++++${Z} ${B}| | | | | | | |${Z}
216
+ # ${R}+++++++++++${Z} ${B}| |__| | __ _ _ _ ___ __ _ ___ | | __| |${Z}
217
+ # ${R}++++++++++${Z} ${B}| __ |/ _\` | | | / __|/ _\` |/ _ \| |/ _\` |${Z}
218
+ # ${R}++++++++++${Z} ${B}| | | | (_| | |_| \__ \ (_| | (_) | | (_| |${Z}
219
+ # ${R}+++++++++${Z} ${B}|_| |_|\__,_|\__,_|___/\__, |\___/|_|\__,_|${Z}
220
+ # ${R}+++++++${Z} ${B}+++${Z} ${B}__/ |${Z}
221
+ # ${R}++++++${Z} ${B}+++++${Z} ${B}|___/${Z}
222
+ # ${R}++++${Z} ${B}+++++++${Z}
223
+ # ${R}+++${Z} ${B}++++++++++${Z} ${COLOR}Apache Kafka Playground${NORMAL}
224
+ #
225
+ ##########
226
+
227
+ EOF
228
+ playground
229
+
230
+ # Rebind enter key to insert newline before command output
231
+ trap 'echo -e "\e[0m"' DEBUG
@@ -0,0 +1,3 @@
1
+ bootstrap.servers=kafka.playground.local:9092
2
+ client.id=kcat
3
+ schema.registry.url=http://schema-registry.playground.local
@@ -0,0 +1,2 @@
1
+ install: --no-ri --no-rdoc
2
+ update: --no-ri --no-rdoc
@@ -0,0 +1,17 @@
1
+ # mappings for Ctrl-left-arrow and Ctrl-right-arrow for word moving
2
+ "\e[1;5C": forward-word
3
+ "\e[1;5D": backward-word
4
+ "\e[5C": forward-word
5
+ "\e[5D": backward-word
6
+ "\e\e[C": forward-word
7
+ "\e\e[D": backward-word
8
+
9
+ # handle common Home/End escape codes
10
+ "\e[1~": beginning-of-line
11
+ "\e[4~": end-of-line
12
+ "\e[7~": beginning-of-line
13
+ "\e[8~": end-of-line
14
+ "\eOH": beginning-of-line
15
+ "\eOF": end-of-line
16
+ "\e[H": beginning-of-line
17
+ "\e[F": end-of-line
@@ -0,0 +1,69 @@
1
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
2
+ require 'bundler/setup' # Set up gems listed in the Gemfile.
3
+ require 'active_support'
4
+ require 'active_support/all'
5
+ require 'json'
6
+ require 'pp'
7
+
8
+ Bundler.require(:default)
9
+ ActiveSupport.eager_load!
10
+
11
+ AppLogger = Logger.new(STDOUT)
12
+ AppLogger.level = Logger::FATAL
13
+ AppLogger.level = Logger::DEBUG if ENV.fetch('DEBUG', '').match? /true|1|on/
14
+
15
+ Rimless.configure do |conf|
16
+ conf.env = 'production'
17
+ conf.app_name = 'playground_app'
18
+ conf.client_id = 'playground'
19
+ conf.logger = AppLogger
20
+ conf.kafka_brokers = ['kafka://kafka.playground.local:9092']
21
+ conf.schema_registry_url = 'http://schema-registry.playground.local'
22
+ end
23
+
24
+ KafkaClient = Kafka.new(Rimless.configuration.kafka_brokers, logger: AppLogger)
25
+
26
+ # +Resolv+ is a thread-aware DNS resolver library written in Ruby. Some newer
27
+ # networking libraries like excon (>=0.85.0) makes use of it instead of the
28
+ # regular glibc facility. This raises an issue for our local development as we
29
+ # use the mDNS stack which is configured in every Docker image accordingly
30
+ # (Avahi, libnss[-mdns]). The default resolver of +Resolv+ does not include the
31
+ # mDNS stack so we have to reconfigure it here for local usage only.
32
+ #
33
+ # See: https://docs.ruby-lang.org/en/2.5.0/Resolv.html
34
+ require 'resolv'
35
+ Resolv::DefaultResolver.replace_resolvers(
36
+ [
37
+ Resolv::Hosts.new,
38
+ Resolv::MDNS.new,
39
+ Resolv::DNS.new
40
+ ]
41
+ )
42
+
43
+ def topic?(name)
44
+ @topic_conf = KafkaClient.describe_topic(name)
45
+ rescue Kafka::UnknownTopicOrPartition
46
+ false
47
+ end
48
+
49
+ def args!
50
+ app = Thor.descendants.map(&:to_s)
51
+ .reject { |klass| klass.include? '::' }.first
52
+ raise "No Thor application class was found." unless app
53
+ app = app.constantize
54
+
55
+ help = ARGV.any? { |arg| %w[help -h --help].include?(arg) }
56
+ known_cmd = app.all_tasks.key? ARGV.first
57
+
58
+ if ARGV.blank? || help || known_cmd
59
+ ARGV.replace(['help', app.default_task])
60
+ else
61
+ ARGV.unshift(app.default_task)
62
+ end
63
+
64
+ ARGV
65
+ end
66
+
67
+ def debug!(opts)
68
+ AppLogger.level = Logger::DEBUG if opts[:verbose]
69
+ end
@@ -0,0 +1,68 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <svg
3
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
4
+ xmlns:cc="http://creativecommons.org/ns#"
5
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
6
+ xmlns:svg="http://www.w3.org/2000/svg"
7
+ xmlns="http://www.w3.org/2000/svg"
8
+ version="1.1"
9
+ id="Ebene_1"
10
+ x="0px"
11
+ y="0px"
12
+ viewBox="0 0 800 200"
13
+ xml:space="preserve"
14
+ width="800"
15
+ height="200"><metadata
16
+ id="metadata33"><rdf:RDF><cc:Work
17
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
18
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
19
+ id="defs31" />
20
+ <style
21
+ type="text/css"
22
+ id="style2">
23
+ .st0{fill-rule:evenodd;clip-rule:evenodd;fill:#E73E11;}
24
+ .st1{fill-rule:evenodd;clip-rule:evenodd;fill:#0371B9;}
25
+ .st2{fill:#132E48;}
26
+ .st3{font-family:'OpenSans-Bold';}
27
+ .st4{font-size:29.5168px;}
28
+ .st5{fill-rule:evenodd;clip-rule:evenodd;fill:none;}
29
+ .st6{opacity:0.5;fill:#132E48;}
30
+ .st7{font-family:'OpenSans';}
31
+ .st8{font-size:12px;}
32
+ </style>
33
+ <g
34
+ transform="translate(0,1.53584)"
35
+ id="g828"><g
36
+ transform="translate(35.93985,35.66416)"
37
+ id="g8">
38
+ <path
39
+ style="clip-rule:evenodd;fill:#e73e11;fill-rule:evenodd"
40
+ id="path4"
41
+ d="m -0.1,124.4 c 0,0 33.7,-123.2 66.7,-123.2 12.8,0 26.9,21.9 38.8,47.2 -23.6,27.9 -66.6,59.7 -94,76 -7.1,0 -11.5,0 -11.5,0 z"
42
+ class="st0" />
43
+ <path
44
+ style="clip-rule:evenodd;fill:#0371b9;fill-rule:evenodd"
45
+ id="path6"
46
+ d="m 88.1,101.8 c 13.5,-10.4 18.4,-16.2 27.1,-25.4 10,25.7 16.7,48 16.7,48 0,0 -41.4,0 -78,0 14.6,-7.9 18.7,-10.7 34.2,-22.6 z"
47
+ class="st1" />
48
+ </g><text
49
+ y="106.40316"
50
+ x="192.43155"
51
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:29.51733398px;font-family:'Open Sans', sans-serif;-inkscape-font-specification:'OpenSans-Bold, Bold';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#132e48"
52
+ id="text10"
53
+ class="st2 st3 st4">Apache Kafka Playground</text>
54
+ <rect
55
+ style="clip-rule:evenodd;fill:none;fill-rule:evenodd"
56
+ id="rect12"
57
+ height="24"
58
+ width="314.5"
59
+ class="st5"
60
+ y="118.06416"
61
+ x="194.23985" /><text
62
+ y="127.22146"
63
+ x="194.21715"
64
+ style="font-size:12px;font-family:'Open Sans', sans-serif;opacity:0.5;fill:#132e48;-inkscape-font-specification:'Open Sans, sans-serif, Normal';font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;"
65
+ id="text14"
66
+ class="st6 st7 st8">A ready to use local Apache Kafka setup based on containers/mDNS</text>
67
+ </g>
68
+ </svg>
@@ -0,0 +1,83 @@
1
+ version: "3"
2
+ services:
3
+ zookeeper:
4
+ image: zookeeper:3.7
5
+ network_mode: bridge
6
+ ports: ["2181"]
7
+ ulimits:
8
+ # Due to systemd/pam RLIMIT_NOFILE settings (max int inside the
9
+ # container), the Java process seams to allocate huge limits which result
10
+ # in a +unable to allocate file descriptor table - out of memory+ error.
11
+ # Lowering this value fixes the issue for now.
12
+ #
13
+ # See: http://bit.ly/2U62A80
14
+ # See: http://bit.ly/2T2Izit
15
+ nofile:
16
+ soft: 100000
17
+ hard: 100000
18
+
19
+ kafka:
20
+ image: hausgold/kafka:2.1
21
+ network_mode: bridge
22
+ environment:
23
+ MDNS_HOSTNAME: kafka.playground.local
24
+ # See: http://bit.ly/2UDzgqI for Kafka downscaling
25
+ KAFKA_HEAP_OPTS: -Xmx256M -Xms32M
26
+ links:
27
+ - zookeeper
28
+ extra_hosts:
29
+ # Due to missing nss-mdns support on Alpine Linux
30
+ # and the requirement to tell our self who we are
31
+ # for Apache Kafka, we register ourself as hostent.
32
+ - kafka.playground.local:127.0.0.1
33
+ ulimits:
34
+ # Due to systemd/pam RLIMIT_NOFILE settings (max int inside the
35
+ # container), the Java process seams to allocate huge limits which result
36
+ # in a +unable to allocate file descriptor table - out of memory+ error.
37
+ # Lowering this value fixes the issue for now.
38
+ #
39
+ # See: http://bit.ly/2U62A80
40
+ # See: http://bit.ly/2T2Izit
41
+ nofile:
42
+ soft: 100000
43
+ hard: 100000
44
+
45
+ schema-registry:
46
+ image: hausgold/schema-registry:5.1.2
47
+ network_mode: bridge
48
+ environment:
49
+ MDNS_HOSTNAME: schema-registry.playground.local
50
+ # Set the default Apache Avro schema compatibility
51
+ #
52
+ # See: http://bit.ly/2TcpoY1
53
+ # See: http://bit.ly/2Hfo4wj
54
+ SCHEMA_REGISTRY_AVRO_COMPATIBILITY_LEVEL: full
55
+ links:
56
+ - zookeeper
57
+ ulimits:
58
+ # Due to systemd/pam RLIMIT_NOFILE settings (max int inside the
59
+ # container), the Java process seams to allocate huge limits which result
60
+ # in a +unable to allocate file descriptor table - out of memory+ error.
61
+ # Lowering this value fixes the issue for now.
62
+ #
63
+ # See: http://bit.ly/2U62A80
64
+ # See: http://bit.ly/2T2Izit
65
+ nofile:
66
+ soft: 100000
67
+ hard: 100000
68
+
69
+ schema-registry-ui:
70
+ image: hausgold/schema-registry-ui:0.9.5
71
+ network_mode: bridge
72
+ environment:
73
+ MDNS_HOSTNAME: schema-registry-ui.playground.local
74
+ SCHEMAREGISTRY_URL: http://schema-registry.playground.local
75
+
76
+ app:
77
+ build: .
78
+ network_mode: bridge
79
+ working_dir: /app
80
+ volumes:
81
+ - .:/app:${DOCKER_MOUNT_MODE:-rw}
82
+ environment:
83
+ MDNS_HOSTNAME: app.playground.local
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../config/environment'
4
+
5
+ # Setup classes which are Apache Avro schema compatible, can be anything which
6
+ # be converted to a hash via +#to_h+ (eg. OpenStruct, RecursiveOpenStruct,
7
+ # Class, Struct, etc)
8
+ PaymentEvent = Struct.new(:event, :payment,
9
+ keyword_init: true)
10
+
11
+ Payment = Struct.new(:gid, :currency, :net_amount_sum, :items, :state,
12
+ :created_at, :updated_at,
13
+ keyword_init: true)
14
+
15
+ PaymentItem = Struct.new(:gid, :net_amount, :tax_rate, :created_at, :updated_at,
16
+ keyword_init: true)
17
+
18
+ # Setup the real data instances which we serialize with Apache Avro and push to
19
+ # Apache Kafka
20
+ item_1_id = SecureRandom.uuid
21
+ item_1 = PaymentItem.new(gid: "gid://playground-app/PaymentItem/#{item_1_id}",
22
+ net_amount: 499,
23
+ tax_rate: 19,
24
+ created_at: Time.current,
25
+ updated_at: nil)
26
+
27
+ item_2_id = SecureRandom.uuid
28
+ item_2 = PaymentItem.new(gid: "gid://playground-app/PaymentItem/#{item_2_id}",
29
+ net_amount: 1,
30
+ tax_rate: 19,
31
+ created_at: Time.current,
32
+ updated_at: nil)
33
+
34
+ payment_id = SecureRandom.uuid
35
+ payment = Payment.new(gid: "gid://playground-app/Payment/#{payment_id}",
36
+ currency: :eur,
37
+ net_amount_sum: 500,
38
+ state: :authorized,
39
+ items: [item_1, item_2],
40
+ created_at: Time.current,
41
+ updated_at: Time.current)
42
+
43
+ event = PaymentEvent.new(event: :payment_authorized, payment: payment)
44
+ event_hash = Rimless.avro_sanitize(event)
45
+
46
+ pp event_hash
47
+
48
+ Rimless.message(data: event_hash, topic: :payments, schema: :payment_v1_event)
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activesupport", "~> 5.2.2"
6
- gem "railties", "~> 5.2.2"
5
+ gem "activesupport", "~> 5.2.0"
6
+ gem "railties", "~> 5.2.0"
7
7
 
8
8
  gemspec path: "../"