active_webhook 1.0.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 +7 -0
- data/.env.sample +1 -0
- data/.gitignore +63 -0
- data/.rspec +4 -0
- data/.rubocop.yml +86 -0
- data/.todo +48 -0
- data/.travis.yml +14 -0
- data/CHANGELOG.md +5 -0
- data/DEV_README.md +199 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +483 -0
- data/Rakefile +23 -0
- data/active_webhook.gemspec +75 -0
- data/config/environment.rb +33 -0
- data/lib/active_webhook.rb +125 -0
- data/lib/active_webhook/adapter.rb +117 -0
- data/lib/active_webhook/callbacks.rb +53 -0
- data/lib/active_webhook/configuration.rb +105 -0
- data/lib/active_webhook/delivery/base_adapter.rb +96 -0
- data/lib/active_webhook/delivery/configuration.rb +16 -0
- data/lib/active_webhook/delivery/faraday_adapter.rb +19 -0
- data/lib/active_webhook/delivery/net_http_adapter.rb +28 -0
- data/lib/active_webhook/error_log.rb +7 -0
- data/lib/active_webhook/formatting/base_adapter.rb +109 -0
- data/lib/active_webhook/formatting/configuration.rb +18 -0
- data/lib/active_webhook/formatting/json_adapter.rb +19 -0
- data/lib/active_webhook/formatting/url_encoded_adapter.rb +28 -0
- data/lib/active_webhook/hook.rb +9 -0
- data/lib/active_webhook/logger.rb +21 -0
- data/lib/active_webhook/models/configuration.rb +18 -0
- data/lib/active_webhook/models/error_log_additions.rb +15 -0
- data/lib/active_webhook/models/subscription_additions.rb +72 -0
- data/lib/active_webhook/models/topic_additions.rb +70 -0
- data/lib/active_webhook/queueing/active_job_adapter.rb +43 -0
- data/lib/active_webhook/queueing/base_adapter.rb +67 -0
- data/lib/active_webhook/queueing/configuration.rb +15 -0
- data/lib/active_webhook/queueing/delayed_job_adapter.rb +28 -0
- data/lib/active_webhook/queueing/sidekiq_adapter.rb +43 -0
- data/lib/active_webhook/queueing/syncronous_adapter.rb +14 -0
- data/lib/active_webhook/subscription.rb +7 -0
- data/lib/active_webhook/topic.rb +7 -0
- data/lib/active_webhook/verification/base_adapter.rb +31 -0
- data/lib/active_webhook/verification/configuration.rb +13 -0
- data/lib/active_webhook/verification/hmac_sha256_adapter.rb +20 -0
- data/lib/active_webhook/verification/unsigned_adapter.rb +11 -0
- data/lib/active_webhook/version.rb +5 -0
- data/lib/generators/install_generator.rb +20 -0
- data/lib/generators/migrations_generator.rb +24 -0
- data/lib/generators/templates/20210618023338_create_active_webhook_tables.rb +31 -0
- data/lib/generators/templates/active_webhook_config.rb +87 -0
- metadata +447 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: bc8acd1e3d7b0ab18220c1550c4036bd52317f4bf8e57d6ff86935703f241e45
|
4
|
+
data.tar.gz: aac9a54fced0844aa949f155c6df5fbcc6fe386b9df701e6e1ef9fa1d8b4cf2e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d7c48dbcb856125ee8d951e1ad9998e02048a96aaa452b63a1042b98503d5ed003bdecf6efbd2e7012aeed7deb09c27e5a11d64bd72fb61683c642f6ea5f25b8
|
7
|
+
data.tar.gz: ec57e66ad519b0e2a65ed97cd4e750146466a0ffa6ba300826d10c3acf0a55ffb4e49712176d6a9e60afe94b88efc375dacec9444e7de55dec6c7a1fbfc135a8
|
data/.env.sample
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
SIDEKIQ_SOMETHING=1
|
data/.gitignore
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
*~
|
13
|
+
log/*
|
14
|
+
measurement/*
|
15
|
+
|
16
|
+
# Used by dotenv library to load environment variables.
|
17
|
+
.env
|
18
|
+
|
19
|
+
|
20
|
+
# Ignore Byebug command history file.
|
21
|
+
.byebug_history
|
22
|
+
|
23
|
+
## Specific to RubyMotion:
|
24
|
+
.dat*
|
25
|
+
.repl_history
|
26
|
+
build/
|
27
|
+
*.bridgesupport
|
28
|
+
build-iPhoneOS/
|
29
|
+
build-iPhoneSimulator/
|
30
|
+
|
31
|
+
## Specific to RubyMotion (use of CocoaPods):
|
32
|
+
#
|
33
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
34
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
35
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
36
|
+
#
|
37
|
+
# vendor/Pods/
|
38
|
+
|
39
|
+
## Documentation cache and generated files:
|
40
|
+
/.yardoc/
|
41
|
+
/_yardoc/
|
42
|
+
/doc/
|
43
|
+
/rdoc/
|
44
|
+
|
45
|
+
## Environment normalization:
|
46
|
+
/.bundle/
|
47
|
+
/vendor/bundle
|
48
|
+
/lib/bundler/man/
|
49
|
+
|
50
|
+
# for a library or gem, you might want to ignore these files since the code is
|
51
|
+
# intended to run in multiple environments; otherwise, check them in:
|
52
|
+
Gemfile.lock
|
53
|
+
|
54
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
55
|
+
.rvmrc
|
56
|
+
.ruby-version
|
57
|
+
.ruby-gemset
|
58
|
+
|
59
|
+
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
|
60
|
+
# .rubocop-https?--*
|
61
|
+
|
62
|
+
# rspec failure tracking
|
63
|
+
.rspec_status
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# I can't get the requires to work with sublime:
|
2
|
+
# SEE: https://github.com/pderichs/sublime_rubocop/issues/66
|
3
|
+
# -- https://gist.github.com/topher6345/4f921ca3e7938132563e
|
4
|
+
# -- https://forum.sublimetext.com/t/run-command-after-saving-file/44016
|
5
|
+
# -- https://medium.com/devnetwork/running-rubocop-only-on-modified-files-a21aed86e06d
|
6
|
+
# -- https://code.tutsplus.com/tutorials/how-to-create-a-sublime-text-2-plugin--net-22685
|
7
|
+
|
8
|
+
# -- https://github.com/SublimeLinter/SublimeLinter-rubocop/issues/19
|
9
|
+
# -- https://github.com/fnando/sublime-codefmt
|
10
|
+
# -- https://github.com/fnando/sublime-switch-case
|
11
|
+
# -- https://github.com/fnando/sublime-rubocop-completion/issues/1
|
12
|
+
# required these fixes:
|
13
|
+
# -- install PackageDev https://forum.sublimetext.com/t/pathlib-not-found-in-purchased-version/49978
|
14
|
+
# -- download all 3 packages via git clone rather than package manager
|
15
|
+
# -- renamed several files and directories to match
|
16
|
+
# -- brew update
|
17
|
+
# -- brew doctor
|
18
|
+
# -- brew install prettier yapf
|
19
|
+
|
20
|
+
require:
|
21
|
+
- rubocop-performance
|
22
|
+
- rubocop-rspec
|
23
|
+
|
24
|
+
AllCops:
|
25
|
+
TargetRubyVersion: 2.5
|
26
|
+
NewCops: enable
|
27
|
+
|
28
|
+
Style/Documentation:
|
29
|
+
Enabled: false
|
30
|
+
|
31
|
+
Naming/VariableNumber:
|
32
|
+
Enabled: false
|
33
|
+
|
34
|
+
Metrics/BlockLength:
|
35
|
+
Exclude:
|
36
|
+
- "**/*.rake"
|
37
|
+
- "config/**/*"
|
38
|
+
- "Rakefile"
|
39
|
+
- "spec/**/*.rb"
|
40
|
+
- "*.gemspec"
|
41
|
+
|
42
|
+
Layout/LineLength:
|
43
|
+
Max: 120
|
44
|
+
|
45
|
+
Style/BlockComments:
|
46
|
+
Enabled: false
|
47
|
+
|
48
|
+
Style/ClassAndModuleChildren:
|
49
|
+
Enabled: false
|
50
|
+
|
51
|
+
Style/RedundantBegin:
|
52
|
+
Enabled: false
|
53
|
+
|
54
|
+
Style/StringLiterals:
|
55
|
+
EnforcedStyle: single_quotes
|
56
|
+
|
57
|
+
Style/StringLiteralsInInterpolation:
|
58
|
+
Enabled: true
|
59
|
+
|
60
|
+
Style/WordArray:
|
61
|
+
EnforcedStyle: brackets
|
62
|
+
|
63
|
+
Metrics/MethodLength:
|
64
|
+
Max: 15
|
65
|
+
|
66
|
+
Style/HashSyntax:
|
67
|
+
Enabled: false
|
68
|
+
|
69
|
+
Style/StringHashKeys:
|
70
|
+
Enabled: false
|
71
|
+
|
72
|
+
Metrics/AbcSize:
|
73
|
+
Enabled: false
|
74
|
+
|
75
|
+
Layout/DotPosition:
|
76
|
+
Enabled: false
|
77
|
+
|
78
|
+
Lint/AmbiguousBlockAssociation:
|
79
|
+
Exclude:
|
80
|
+
- "spec/**/*"
|
81
|
+
|
82
|
+
RSpec/NamedSubject:
|
83
|
+
Enabled: false
|
84
|
+
# Rails:
|
85
|
+
# Enabled: true
|
86
|
+
|
data/.todo
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
-------------------------------------------------------------------------------------
|
4
|
+
|
5
|
+
...meanwhile, back at planet scope...
|
6
|
+
|
7
|
+
bundle exec rspec spec/gql/v2/objects/organization_type_spec.rb spec/gql/v2/objects/user_type_spec.rb spec/gql/v2/objects/query_type_spec.rb spec/gql/v2/objects/webhook_* spec/gql/v2/mutations/webhook_subscriptions/* spec/libs/acts_as_webhook_spec.rb spec/gql/*/schema_type_spec.rb
|
8
|
+
|
9
|
+
|
10
|
+
1. deploy (wait until friday)
|
11
|
+
1. create new repo
|
12
|
+
1. squash
|
13
|
+
1. push
|
14
|
+
|
15
|
+
|
16
|
+
-------------------------------------------------------------------------------------
|
17
|
+
|
18
|
+
...meanwhile, back at planet active_webbhook...
|
19
|
+
|
20
|
+
1. deploy (wait until friday)
|
21
|
+
1. create new repo
|
22
|
+
1. squash
|
23
|
+
1. push
|
24
|
+
|
25
|
+
-------------------------------------------------------------------------------------
|
26
|
+
# everything below this line is optional
|
27
|
+
|
28
|
+
1. add rate limiting
|
29
|
+
|
30
|
+
1. update the readme
|
31
|
+
- list all config options with brief descriptions (and link to config file for more information)
|
32
|
+
- list all gem dependencies for each adapter
|
33
|
+
- change customization to separate use cases
|
34
|
+
|
35
|
+
1. solve rubygems
|
36
|
+
|
37
|
+
1. fix generator
|
38
|
+
- didn't work for scope
|
39
|
+
- rename active_webhook_config.rb to initializers/active_webhook.rb
|
40
|
+
? add option to install models & factories (see devise) [accept list of models to create & namespace]
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
|
48
|
+
|
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# SEE: https://docs.travis-ci.com/user/languages/ruby/
|
2
|
+
|
3
|
+
language: ruby
|
4
|
+
rvm:
|
5
|
+
- 2.5.3
|
6
|
+
before_install:
|
7
|
+
- gem install bundler:1.17.3
|
8
|
+
install:
|
9
|
+
- bundle _1.17.3_ install --jobs=3 --retry=3
|
10
|
+
- bundle exec rake db:reset
|
11
|
+
env:
|
12
|
+
# - 'TEST_RAILS_VERSION="~> 5.2.3"'
|
13
|
+
# - 'TEST_RAILS_VERSION="~> 6.0.3"'
|
14
|
+
- 'TEST_RAILS_VERSION="~> 6.1.3.2"'
|
data/CHANGELOG.md
ADDED
data/DEV_README.md
ADDED
@@ -0,0 +1,199 @@
|
|
1
|
+
## inspired by
|
2
|
+
|
3
|
+
`https://benediktdeicke.com/2017/09/sending-webhooks-with-rails/`
|
4
|
+
|
5
|
+
## look at importing server from https://github.com/nsweeting/activehook
|
6
|
+
|
7
|
+
## bootstrapped with:
|
8
|
+
|
9
|
+
`bundle gem active_webhook --test=rspec --mit`
|
10
|
+
|
11
|
+
## bootstrapped dummy rails app with
|
12
|
+
|
13
|
+
`rails new dummy --skip-spring --skip-listen --skip-bootsnap --skip-action-text --skip-active-storage --skip-action-cable --skip-action-mailer --skip-action-mailbox --skip-test --skip-system-test --skip-active-job --skip-active-record --skip-javascript`
|
14
|
+
|
15
|
+
[then dicarded and used fully dummy]
|
16
|
+
|
17
|
+
[SEE](https://lokalise.com/blog/create-a-ruby-gem-basics/)
|
18
|
+
[SEE](https://lokalise.com/blog/how-to-create-a-ruby-gem-testing-suite/)
|
19
|
+
|
20
|
+
rails d model active_webhook/subscription
|
21
|
+
|
22
|
+
rails d model active_webhook/topic
|
23
|
+
|
24
|
+
rails g model active_webhook/subscription \
|
25
|
+
user_id:integer \
|
26
|
+
state:tinyint \
|
27
|
+
topic_key:string \
|
28
|
+
topic_version:string \
|
29
|
+
updated_at:datetime \
|
30
|
+
disabled_reason:string \
|
31
|
+
format:string \
|
32
|
+
callback_url:text \
|
33
|
+
company_id:integer \
|
34
|
+
query:text
|
35
|
+
|
36
|
+
rails g model active_webhook/topic \
|
37
|
+
key:string \
|
38
|
+
version:string \
|
39
|
+
state:tinyint \
|
40
|
+
query:string \
|
41
|
+
|
42
|
+
|
43
|
+
-------------------------------------------------------------------------------------
|
44
|
+
# everything below this line is deferred until needed
|
45
|
+
|
46
|
+
1. consolidate formatting/*_adapter.rb into hook/builder.rb
|
47
|
+
- change content_type & encoded_data methods use ActiveWebhook.configuration.content_type
|
48
|
+
- add ActiveWebhook.configuration.builder
|
49
|
+
- delete Hook (in favor of basic hash) ?
|
50
|
+
|
51
|
+
1. add `config.queueing.delay` trigger(in: nil) => [1.second]
|
52
|
+
- do not add to Topic or Subscription models (because they aren't loaded before check for performance reasons)
|
53
|
+
- evaluate to config.nil? ? method.option : config.value
|
54
|
+
- configure each queuing adapter to pass delay to underlying implementation
|
55
|
+
|
56
|
+
1. add `config.buffering.adapter` => [:disabled, :enabled, Buffering::BaseAdapter]
|
57
|
+
- introduce shim into queueing/base_adapter#call that passes to active_webbhook/buffer/*adapter and back
|
58
|
+
- make sure that all queuing adapters delay after buffer is flushed
|
59
|
+
- add buffer/disabled_adapter and buffer/enabled_adapter
|
60
|
+
- implement as follows:
|
61
|
+
- if enabled, require `request_store`
|
62
|
+
- monkey_patch transaction block (or observe callbacks)
|
63
|
+
- add `buffer.t_level` and `buffer.entries`
|
64
|
+
- store t_level with buffer entry args
|
65
|
+
- on rollback, `buffer.entries.delete` where `entry.t_level` >= `buffer.t_level`; then `buffer.t_level -= 1`
|
66
|
+
- on commit, `buffer.entries.t.level -= 1` where `entry.t_level` >= `buffer.t_level`; then `buffer.t_level -= 1`
|
67
|
+
- if rails, `ActionController.include ActiveWebhook::Buferable` that wraps each action with `begin; ActiveWebhook.buffer.start; ensure; ActiveWebhook.buffer.flush; end
|
68
|
+
- note: Def controller might require different implementation from transactions; need to research transaction callbacks and commits during transaction
|
69
|
+
- https://github.com/steveklabnik/request_store
|
70
|
+
- https://www.justinweiss.com/articles/better-globals-with-a-tiny-activesupport-module/
|
71
|
+
|
72
|
+
1. add `ActiveWebhook.cancel(...same args as trigger)`
|
73
|
+
- clears matching `buffer.entries` via `buffer.cancel(**kwargs)`
|
74
|
+
- relies on `config.buffer.eq?(a, b)`
|
75
|
+
|
76
|
+
1. add `config.buffering.remove_duplicates` and trigger(remove_duplicates: nil, **) [true, false]
|
77
|
+
- do not add to Topic or Subscription models (because they aren't loaded before check for performance reasons)
|
78
|
+
- evaluate to config.nil? ? method.option : config.value
|
79
|
+
- raise runtime error if true and bufferring_adapter is disabled
|
80
|
+
- relies on `config.buffer.eq?(a, b)`
|
81
|
+
|
82
|
+
1. add `config.delivery.retry_count` and trigger(retry_count: nil, **) [true, false]
|
83
|
+
- do not add to Topic or Subscription models (because they aren't loaded before check for performance reasons)
|
84
|
+
- evaluate to config.nil? ? method.option : config.value
|
85
|
+
- solve how to specify retry count with exponential backoff for each queuing adapter
|
86
|
+
- match option name to active_job
|
87
|
+
|
88
|
+
1. add `config.delivery.time_limit` and trigger(time_limit: nil, **) [true, false]
|
89
|
+
- do not add to Topic or Subscription models (because they aren't loaded before check for performance reasons)
|
90
|
+
- evaluate to config.nil? ? method.option : config.value
|
91
|
+
- solve how to specify time limit for each queuing adapter
|
92
|
+
- match option name to active_job
|
93
|
+
|
94
|
+
1. add jid to context in syncronous queuing adapter (if possible)
|
95
|
+
- solve how to generate an auto increment Id across servers (maybe hash or hex a server id and counter; could store server in db and load on start)
|
96
|
+
- https://www.google.com/search?q=rails+set+global+variable+per+request&client=safari&hl=en-us&ei=xF3NYKDaKYX_-wSAu5KIAw&oq=rails+set+global+variable+per+request
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
Scratchpad
|
101
|
+
---
|
102
|
+
# in spec/spec_helper.rb
|
103
|
+
|
104
|
+
# Restablish connection (severed from app load)
|
105
|
+
ActiveRecord::Base.establish_connection(DB_CONFIG)
|
106
|
+
|
107
|
+
# log sql (as level debug)
|
108
|
+
ActiveRecord::Base.logger = Rails.logger
|
109
|
+
|
110
|
+
|
111
|
+
----
|
112
|
+
# in Rakefile
|
113
|
+
|
114
|
+
# require "bundler/gem_tasks"
|
115
|
+
# require "rspec/core/rake_task"
|
116
|
+
# Bundler::GemHelper.install_tasks
|
117
|
+
# rescue LoadError
|
118
|
+
# puts "although not required, bundler is recommended for running the tests"
|
119
|
+
# end
|
120
|
+
# require "rake"
|
121
|
+
|
122
|
+
# RSpec::Core::RakeTask.new(:spec) do |spec|
|
123
|
+
# spec.pattern = 'spec/**/*_spec.rb'
|
124
|
+
# end
|
125
|
+
|
126
|
+
# namespace :db do
|
127
|
+
# desc "Create the database"
|
128
|
+
# task :create do
|
129
|
+
# initialize_rake_environment
|
130
|
+
# if ActiveRecord::Base.connection.respond_to? :create_database
|
131
|
+
# ActiveRecord::Base.connection.create_database(DB_CONFIG["database"])
|
132
|
+
# else
|
133
|
+
# ActiveRecord::Base.connection.send :connect
|
134
|
+
# end
|
135
|
+
# puts "Database created."
|
136
|
+
# end
|
137
|
+
|
138
|
+
# desc "Migrate the database"
|
139
|
+
# task :migrate do
|
140
|
+
# initialize_rake_environment
|
141
|
+
# ActiveRecord::Base.connection.migration_context.migrate
|
142
|
+
# Rake::Task["db:schema"].invoke
|
143
|
+
# puts "Database migrated."
|
144
|
+
# end
|
145
|
+
|
146
|
+
# desc "Drop the database"
|
147
|
+
# task :drop do
|
148
|
+
# initialize_rake_environment
|
149
|
+
# ActiveRecord::Base.connection.close
|
150
|
+
# if ActiveRecord::Base.connection.respond_to? :drop_database
|
151
|
+
# ActiveRecord::Base.connection.drop_database(DB_CONFIG["database"])
|
152
|
+
# else
|
153
|
+
# f = [__dir__, "db", "#{ENV['RACK_ENV']}.sqlite3"].join("/")
|
154
|
+
# File.delete(f) if File.exist?(f)
|
155
|
+
# end
|
156
|
+
# puts "Database deleted."
|
157
|
+
# end
|
158
|
+
|
159
|
+
# desc "Reset the database"
|
160
|
+
# task :reset => %i[drop create migrate]
|
161
|
+
|
162
|
+
# desc "Create a db/schema.rb file that is portable against any DB supported by AR"
|
163
|
+
# task :schema do
|
164
|
+
# initialize_rake_environment
|
165
|
+
# require "active_record/schema_dumper"
|
166
|
+
# filename = "db/schema.rb"
|
167
|
+
# File.open(filename, "w:utf-8") do |file|
|
168
|
+
# ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
169
|
+
# end
|
170
|
+
# end
|
171
|
+
# end
|
172
|
+
|
173
|
+
# namespace :g do
|
174
|
+
# desc "Generate migration"
|
175
|
+
# task :migration do
|
176
|
+
# initialize_rake_environment
|
177
|
+
# name = ARGV[1] || raise("Specify name: rake g:migration your_migration")
|
178
|
+
# timestamp = Time.now.strftime("%Y%m%d%H%M%S")
|
179
|
+
# path = File.expand_path("../db/migrate/#{timestamp}_#{name}.rb", __FILE__)
|
180
|
+
# migration_class = name.split("_").map(&:capitalize).join
|
181
|
+
|
182
|
+
# File.open(path, "w") do |file|
|
183
|
+
# file.write <<~FILE
|
184
|
+
# class #{migration_class} < ActiveRecord::Migration
|
185
|
+
# def self.up
|
186
|
+
# end
|
187
|
+
# def self.down
|
188
|
+
# end
|
189
|
+
# end
|
190
|
+
# FILE
|
191
|
+
# end
|
192
|
+
|
193
|
+
# puts "Migration #{path} created"
|
194
|
+
# abort # needed stop other tasks
|
195
|
+
# end
|
196
|
+
# end
|
197
|
+
|
198
|
+
|
199
|
+
|