close_encounters 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a24140efc0d1f7aa0f701d7c7ac16a1ced62c808d44224220dff606156cc08b3
4
+ data.tar.gz: cbf2f638428e2526cec682ba2250c465632f4aad9d8028135d61c63fac99f9ce
5
+ SHA512:
6
+ metadata.gz: 5a7cd81cdb97205774b919c928fd81ba896fa22300784171a8e3037c0d5a1243c5da1e8587d7c616b7e7ead0b3973cc4fa06cada1579ec22af4b5170c87dc670
7
+ data.tar.gz: 85223a244ef256129651b57eb089f712732eb24be7c80fcf1b969017c0b45d88d0c93fe9b7114d1ff0691a05cada6ad31836e85f0129feab303765e2f365b70e
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Change log
2
+ All notable changes to this project will be documented in this file.
3
+
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/).
6
+
7
+ ## Unreleased
8
+ ### Added:
9
+ - Initial implimentation
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright Jim Gay
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # CloseEncounters
2
+ Add serices and events that can track responses from third-party services.
3
+
4
+ ## Usage
5
+ Install it like any other rails engine.
6
+
7
+ ```ruby
8
+ rails close_encounters:install:migrations
9
+ ```
10
+
11
+ Then when you have it installed and migrated you can start tracking events.
12
+
13
+ ```ruby
14
+ response = SomeThirdPartyService.call
15
+ CloseEncounters.contact("SomeThirdPartyService", status: response.status.to_i, response.body)
16
+ ```
17
+
18
+ If the services regularly returns 200 responses, no new events will be recorded.
19
+ When it switches to a different status, a new event will be recorded.
20
+
21
+ ```ruby
22
+ CloseEncounters.status("SomeThirdPartyService") # => 200
23
+ # evuntually you use `contact` and it records a 500 and you'll be able to get
24
+ CloseEncounters.status("SomeThirdPartyService") # => 500
25
+ ```
26
+
27
+ ## Installation
28
+ Add this line to your application's Gemfile:
29
+
30
+ ```ruby
31
+ gem "close_encounters"
32
+ ```
33
+
34
+ And then execute:
35
+ ```bash
36
+ $ bundle
37
+ ```
38
+
39
+ Or install it yourself as:
40
+ ```bash
41
+ $ gem install close_encounters
42
+ ```
43
+
44
+ ## License
45
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
9
+
10
+ require "rake/testtask"
11
+
12
+ Rake::TestTask.new do |t|
13
+ t.libs << "test"
14
+ t.pattern = "test/**/*_test.rb"
15
+ end
16
+
17
+ task default: ["db:setup", "db:migrate", "app:environment", :test] # Modify default task
@@ -0,0 +1,5 @@
1
+ module CloseEncounters
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module CloseEncounters
2
+ class ParticipantEvent < ApplicationRecord
3
+ belongs_to :participant_service, inverse_of: :events, class_name: "CloseEncounters::ParticipantService"
4
+
5
+ scope :newest, -> { order(created_at: :desc).first }
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module CloseEncounters
2
+ class ParticipantService < ApplicationRecord
3
+ has_many :events, inverse_of: :participant_service, class_name: "CloseEncounters::ParticipantEvent"
4
+
5
+ validates :name, presence: true
6
+
7
+ if columns_hash["connection_info"].type == :text
8
+ serialize :connection_info, coder: JSON
9
+ end
10
+
11
+ encrypts :connection_info
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ class CreateCloseEncountersParticipantServices < ActiveRecord::Migration[7.1]
2
+ def change
3
+ create_table :close_encounters_participant_services do |t|
4
+ t.string :name, null: false
5
+ if ActiveRecord::Base.connection.adapter_name.downcase.include?("postgresql")
6
+ t.jsonb :connection_info
7
+ else
8
+ t.text :connection_info
9
+ end
10
+
11
+ t.timestamps
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,11 @@
1
+ class CreateCloseEncountersParticipantEvents < ActiveRecord::Migration[7.1]
2
+ def change
3
+ create_table :close_encounters_participant_events do |t|
4
+ t.text :response
5
+ t.references :close_encounters_participant_service, null: false, foreign_key: true
6
+ t.integer :status, null: false
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,16 @@
1
+ class AddCloseEcountersIndexes < ActiveRecord::Migration[7.1]
2
+ disable_ddl_transaction!
3
+
4
+ def change
5
+ options = if self.class.adapter_name.match?(/postgres/i)
6
+ {algorithm: :concurrently}
7
+ else
8
+ {}
9
+ end
10
+
11
+ add_index :close_encounters_participant_services,
12
+ :name,
13
+ unique: true,
14
+ **options
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module CloseEncounters
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace CloseEncounters
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module CloseEncounters
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,39 @@
1
+ require "close_encounters/version"
2
+ require "close_encounters/engine"
3
+
4
+ module CloseEncounters
5
+ module_function
6
+
7
+ autoload :ParticipantService, "close_encounters/participant_service"
8
+ autoload :ParticipantEvent, "close_encounters/participant_event"
9
+
10
+ # Record a contact with a third party service if the status has changed
11
+ #
12
+ # @param name [String] the name of the service
13
+ # @param status [Integer] the HTTP status of the contact
14
+ # @param response [String] the response object
15
+ def contact(name, status:, response:)
16
+ service = ParticipantService.find_by!(name:)
17
+ unless service.events.newest.status == status
18
+ service.events.create!(status: status, response:)
19
+ end
20
+ end
21
+
22
+ # Get the status of the most recent contact with a third party service
23
+ #
24
+ # @param name [String] the name of the service
25
+ # @return [Integer] the HTTP status of the most recent contact
26
+ def status(name)
27
+ ParticipantService.find_by!(name: name).events.newest.status
28
+ end
29
+
30
+ # Ensure that a participant service exists
31
+ #
32
+ # @param name [String] the name of the service
33
+ # @param connection_info [Hash] the connection information for the service
34
+ def ensure_service(name, connection_info: {})
35
+ ParticipantService.find_or_create_by!(name: name) do |service|
36
+ service.connection_info = connection_info
37
+ end
38
+ end
39
+ end
metadata ADDED
@@ -0,0 +1,144 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: close_encounters
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Jim Gay
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: railties
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '7.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '7.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activerecord
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: actionpack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: actionview
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: activesupport
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rails-controller-testing
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Keep track of responses from third party systems. Use this to monitor
98
+ and respond to changes in status.
99
+ email:
100
+ - jim@saturnflyer.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - CHANGELOG.md
106
+ - MIT-LICENSE
107
+ - README.md
108
+ - Rakefile
109
+ - app/models/close_encounters/application_record.rb
110
+ - app/models/close_encounters/participant_event.rb
111
+ - app/models/close_encounters/participant_service.rb
112
+ - db/migrate/20240430173723_create_close_encounters_participant_services.rb
113
+ - db/migrate/20240430173725_create_close_encounters_participant_events.rb
114
+ - db/migrate/20240508190642_add_close_ecounters_indexes.rb
115
+ - lib/close_encounters.rb
116
+ - lib/close_encounters/engine.rb
117
+ - lib/close_encounters/version.rb
118
+ homepage: https://github.com/SOFware/close_encounters
119
+ licenses:
120
+ - MIT
121
+ metadata:
122
+ homepage_uri: https://github.com/SOFware/close_encounters
123
+ source_code_uri: https://github.com/SOFware/close_encounters
124
+ changelog_uri: https://github.com/SOFware/close_encounters/blob/main/CHANGELOG.md
125
+ post_install_message:
126
+ rdoc_options: []
127
+ require_paths:
128
+ - lib
129
+ required_ruby_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubygems_version: 3.5.9
141
+ signing_key:
142
+ specification_version: 4
143
+ summary: Close Encounters of the Third Party
144
+ test_files: []