rimless 1.2.0 → 1.4.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.
- 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)
|