rimless 1.2.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/documentation.yml +3 -2
- data/.github/workflows/release.yml +47 -0
- data/.github/workflows/test.yml +6 -9
- data/.rspec +2 -2
- data/.rubocop.yml +16 -2
- data/.simplecov +12 -0
- data/Appraisals +2 -22
- data/CHANGELOG.md +16 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Dockerfile +2 -3
- data/Envfile +0 -3
- data/Guardfile +44 -0
- data/LICENSE +1 -1
- data/Makefile +18 -7
- data/README.md +21 -8
- data/Rakefile +13 -68
- data/doc/kafka-playground/.gitignore +2 -0
- data/doc/kafka-playground/Dockerfile +41 -0
- data/doc/kafka-playground/Gemfile +8 -0
- data/doc/kafka-playground/Gemfile.lock +155 -0
- data/doc/kafka-playground/Makefile +209 -0
- data/doc/kafka-playground/README.md +185 -0
- data/doc/kafka-playground/bin/consume-topic +7 -0
- data/doc/kafka-playground/bin/create-topic +42 -0
- data/doc/kafka-playground/bin/delete-topic +22 -0
- data/doc/kafka-playground/bin/list-topics +3 -0
- data/doc/kafka-playground/bin/produce-event +64 -0
- data/doc/kafka-playground/config/avro_schemas/.gitignore +1 -0
- data/doc/kafka-playground/config/avro_schemas/playground_app/item_v1.avsc.erb +36 -0
- data/doc/kafka-playground/config/avro_schemas/playground_app/payment_v1.avsc.erb +59 -0
- data/doc/kafka-playground/config/avro_schemas/playground_app/payment_v1_event.avsc.erb +18 -0
- data/doc/kafka-playground/config/docker/shell/.bash_profile +3 -0
- data/doc/kafka-playground/config/docker/shell/.bashrc +231 -0
- data/doc/kafka-playground/config/docker/shell/.config/kcat.conf +3 -0
- data/doc/kafka-playground/config/docker/shell/.gemrc +2 -0
- data/doc/kafka-playground/config/docker/shell/.inputrc +17 -0
- data/doc/kafka-playground/config/environment.rb +69 -0
- data/doc/kafka-playground/doc/assets/project.svg +68 -0
- data/doc/kafka-playground/docker-compose.yml +83 -0
- data/doc/kafka-playground/examples/rimless-produce +48 -0
- data/gemfiles/rails_5.2.gemfile +2 -2
- data/lib/rimless/configuration_handling.rb +11 -1
- data/lib/rimless/consumer.rb +4 -2
- data/lib/rimless/dependencies.rb +3 -0
- data/lib/rimless/kafka_helpers.rb +2 -0
- data/lib/rimless/karafka/avro_deserializer.rb +3 -3
- data/lib/rimless/rspec/helpers.rb +3 -0
- data/lib/rimless/rspec/matchers.rb +3 -4
- data/lib/rimless/rspec.rb +1 -1
- data/lib/rimless/tasks/consumer.rake +3 -0
- data/lib/rimless/tasks/generator.rake +3 -0
- data/lib/rimless/tasks/stats.rake +5 -2
- data/lib/rimless/version.rb +18 -1
- data/lib/rimless.rb +0 -1
- data/rimless.gemspec +43 -29
- metadata +124 -79
- data/gemfiles/rails_4.2.gemfile +0 -8
- data/gemfiles/rails_5.0.gemfile +0 -8
- data/gemfiles/rails_5.1.gemfile +0 -8
- 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,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,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)
|