nexo 0.1.2 → 0.1.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 762b84bd5b5d458091d881a7227c7680048e1ae206e4eef1e6d94246e7be238b
4
- data.tar.gz: e5358a64b012b93ffbc7a2f67c21e5179df2d7a7a5581771c1ee97c2466b20e9
3
+ metadata.gz: 8e9cc07511456093aa96d53df983acf4bfc770ba3de05df5bacfb683f80840ca
4
+ data.tar.gz: 5b1918e753e917ac5e0331aa5d49fe03a5d0fcb87d64fc36bab85af638b79246
5
5
  SHA512:
6
- metadata.gz: ecf2eb80621fdce1e6d137dc6d5122fe66db21d893349a86e75d1e4251f73dd120eb6cc3e7f2d899b461a118a20dee7e4fa60ed919819a15204a4787fcde7ca2
7
- data.tar.gz: 2389d6ea2996feeeae34a3256ca89037f5d2b0acf658d6e02345d349b5e44712870fd32ed3e7e3421dcd37a1068be3aa83ecba5e74cf221ad312f4797659ca88
6
+ metadata.gz: 973db6311a60eb0534b3ca072976190bb3b5be953bc3b8f6cbb6e39207ba127b54711dd5ec0adbcc3f2c5cc4c4272302ca558ad0572c687f6864402e7bec4bde
7
+ data.tar.gz: 79ba89ed8a6dbbd17bdf8c6c055df802fb9ec4cca686075d2f5e2653c776d1b38599371158bd58fb3779aef6dffd8718bd9ea8b5c42e2403a30d917a5aa72505
data/README.md CHANGED
@@ -21,6 +21,11 @@ Or install it yourself as:
21
21
  $ gem install nexo
22
22
  ```
23
23
 
24
+ Install good_job
25
+ Configure good_job
26
+ max_threads:
27
+ queues:
28
+
24
29
  ## Contributing
25
30
  Contribution directions go here.
26
31
 
@@ -7,6 +7,9 @@ module Nexo
7
7
 
8
8
  queue_as :api_clients
9
9
 
10
+ # TODO!: configure good job queues and thread pools
11
+ # https://github.com/bensheldon/good_job?tab=readme-ov-file#optimize-queues-threads-and-processes
12
+ # TODO: make this configurable, so other job backends are allowed
10
13
  good_job_control_concurrency_with(
11
14
  perform_limit: 1,
12
15
 
@@ -18,7 +21,10 @@ module Nexo
18
21
  retry_on(
19
22
  GoodJob::ActiveJobExtensions::Concurrency::ConcurrencyExceededError,
20
23
  attempts: Float::INFINITY,
21
- wait: ->(executions) { ((executions**3) + (Kernel.rand * (executions**3) * 0.5)) + 2 }
24
+ wait: :polynomially_longer,
25
+ jitter: 0.99,
26
+ # wait: ->(executions) { ((executions**4) + (Kernel.rand * (executions**4) * jitter)) + 2 }
27
+ # wait: ->(executions) { ((executions**3) + (Kernel.rand * (executions**3) * 0.5)) + 2 }
22
28
  )
23
29
  end
24
30
  end
@@ -4,6 +4,8 @@ module Nexo
4
4
  if folder.external_identifier.present?
5
5
  protocol_service = ServiceBuilder.instance.build_protocol_service(folder)
6
6
  response = protocol_service.remove_calendar(folder)
7
+ else
8
+ Rails.logger.info("Folder doesn't have external_identifier: #{folder.to_gid}")
7
9
  end
8
10
  end
9
11
  end
@@ -1,10 +1,12 @@
1
1
  module Nexo
2
2
  class FolderSyncJob < BaseJob
3
3
  def perform(folder)
4
+ protocol_service = ServiceBuilder.instance.build_protocol_service(folder)
4
5
  if folder.external_identifier.blank?
5
- protocol_service = ServiceBuilder.instance.build_protocol_service(folder)
6
6
  response = protocol_service.insert_calendar(folder)
7
7
  folder.update(external_identifier: response.id)
8
+ else
9
+ protocol_service.update_calendar(folder)
8
10
  end
9
11
 
10
12
  policies = PolicyService.instance.policies_for(folder)
@@ -14,6 +14,8 @@ module Nexo
14
14
  class SyncElementJob < BaseJob
15
15
  limits_concurrency key: ->(element) { element.to_gid }
16
16
 
17
+ # TODO!: set priority based on date distance to today
18
+
17
19
  # discard_on Errors::SyncElementJobError
18
20
  # retry_on StandardError, wait: :polynomially_longer
19
21
 
@@ -26,6 +26,18 @@ module Nexo
26
26
  private
27
27
 
28
28
  def validate_element_state!
29
+ if element.synchronizable.blank?
30
+ raise Errors::SynchronizableNotFound
31
+ end
32
+
33
+ if element.synchronizable.respond_to?(:discarded?) && element.synchronizable.discarded?
34
+ raise Errors::SynchronizableDiscarded
35
+ end
36
+
37
+ if element.folder.discarded?
38
+ raise Errors::FolderDiscarded
39
+ end
40
+
29
41
  if element.synchronizable.conflicted?
30
42
  raise Errors::ElementConflicted
31
43
  end
@@ -3,8 +3,10 @@ module Nexo
3
3
  #
4
4
  # @raise [Google::Apis::ClientError] possible messages:
5
5
  # - duplicate: The requested identifier already exists.
6
- # - notFound: Not Found
7
- # - forbidden: Forbidden (cuando se intenta updatear un evento que ya fue borrado)
6
+ # - notFound: Not Found (calendar not exists or was deleted)
7
+ # - forbidden: Forbidden (event to update was deleted)
8
+ #
9
+ # TODO! when event to update was deleted, create a new one and warn
8
10
  class GoogleCalendarService < CalendarService
9
11
  # Create an event in a Google Calendar
10
12
  #
@@ -44,6 +46,13 @@ module Nexo
44
46
  ApiResponse.new(payload: response.to_json, status: :ok, etag: response.etag, id: response.id)
45
47
  end
46
48
 
49
+ # Create a Google calendar
50
+ def update_calendar(folder)
51
+ cal = build_calendar(folder)
52
+ response = client.update_calendar(cal)
53
+ ApiResponse.new(payload: response.to_json, status: :ok, etag: response.etag, id: response.id)
54
+ end
55
+
47
56
  def remove_calendar(folder)
48
57
  client.delete_calendar(folder.external_identifier)
49
58
  ApiResponse.new(status: :ok)
@@ -7,6 +7,8 @@ module Nexo
7
7
  class ElementAlreadySynced < Error; end
8
8
  class MoreThanOneElementInFolderForSynchronizable < Error; end
9
9
  class InvalidFolderState < Error; end
10
+ class FolderDiscarded < Error; end
11
+ class SynchronizableDiscarded < Error; end
10
12
 
11
13
  # on ControllerHelper
12
14
  class InvalidParamsError < Error; end
@@ -10,7 +10,7 @@ module Nexo
10
10
  end
11
11
 
12
12
  def build_protocol_service(folder)
13
- service_klass_name = "#{folder.integration.client.service}_#{folder.protocol}_service".camelcase
13
+ service_klass_name = "#{folder.integration.client.service}_#{folder.nexo_protocol}_service".camelcase
14
14
  build_service(service_klass_name, folder.integration)
15
15
  end
16
16
 
@@ -62,7 +62,7 @@ module Nexo
62
62
  def update_from!(element_version)
63
63
  transaction do
64
64
  # TODO: parse the element_version.payload
65
- # and set the Synchronizable fields according to the Folder#protocol
65
+ # and set the Synchronizable fields according to the Folder#nexo_protocol
66
66
 
67
67
  new_sequence = increment_sequence!
68
68
  element_version.update_sequence!(new_sequence)
@@ -29,8 +29,7 @@ module Nexo
29
29
  enum :service, google: 0
30
30
  enum :tcp_status, authorized: 0, disabled: 1, expired: 2
31
31
 
32
- validates :service, :user_integrations_allowed,
33
- :tcp_status, :secret, presence: true
32
+ validates :service, :tcp_status, :secret, presence: true
34
33
 
35
34
  serialize :secret, coder: JSON
36
35
 
@@ -18,14 +18,14 @@ module Nexo
18
18
  has_many :elements, class_name: "Nexo::Element"
19
19
 
20
20
  if respond_to?(:enumerize)
21
- enumerize :protocol, in: { calendar: 0, dummy_calendar: 1 }
21
+ enumerize :nexo_protocol, in: { calendar: 0, dummy_calendar: 1 }
22
22
  else
23
- enum :protocol, calendar: 0, dummy_calendar: 1
23
+ enum :nexo_protocol, calendar: 0, dummy_calendar: 1
24
24
  end
25
25
 
26
26
  scope :kept, -> { where(discarded_at: nil) }
27
27
 
28
- validates :protocol, :name, presence: true
28
+ validates :nexo_protocol, :name, presence: true
29
29
 
30
30
  # TODO!: find better name
31
31
  # maybe policy_applies?
@@ -21,6 +21,11 @@ module Nexo
21
21
  belongs_to :user
22
22
  belongs_to :client, class_name: "Nexo::Client"
23
23
  has_many :tokens, class_name: "Nexo::Token"
24
+ has_many :folders, class_name: "Nexo::Folder"
25
+
26
+ before_validation do
27
+ self.scope = scope.select(&:present?)
28
+ end
24
29
 
25
30
  validates :scope, presence: true
26
31
 
@@ -5,7 +5,6 @@ class CreateNexoClients < ActiveRecord::Migration[7.2]
5
5
  t.string :secret
6
6
  t.integer :tcp_status
7
7
  t.integer :brand_name
8
- t.boolean :user_integrations_allowed
9
8
 
10
9
  t.timestamps
11
10
  end
@@ -2,7 +2,7 @@ class CreateNexoFolders < ActiveRecord::Migration[7.2]
2
2
  def change
3
3
  create_table :nexo_folders do |t|
4
4
  t.references :integration, null: false, foreign_key: { to_table: :nexo_integrations }
5
- t.integer :protocol, null: false
5
+ t.integer :nexo_protocol, null: false
6
6
  t.string :external_identifier
7
7
  t.string :name
8
8
  t.string :description
data/db/seeds.rb CHANGED
@@ -1,3 +1,28 @@
1
1
  module Nexo
2
- # Nexo seeds
2
+ ENV.fetch('SEED_GOOGLE_APIS_CLIENT_SECRET', nil) || puts("WARN: env variable SEED_GOOGLE_APIS_CLIENT_SECRET not found")
3
+ ENV.fetch('SEED_GOOGLE_APIS_TOKEN', nil) || puts("WARN: env variable SEED_GOOGLE_APIS_TOKEN not found")
4
+
5
+ if ENV.fetch('SEED_GOOGLE_APIS_CLIENT_SECRET', nil)
6
+ client = Client.create!(
7
+ tcp_status: 0,
8
+ service: "google",
9
+ secret: JSON.parse(ENV.fetch('SEED_GOOGLE_APIS_CLIENT_SECRET'))
10
+ )
11
+ user = User.first
12
+ integration = Nexo::Integration.create!(
13
+ user:,
14
+ client:,
15
+ name: "Default integration",
16
+ scope: [ "auth_calendar_app_created" ]
17
+ )
18
+
19
+ if ENV.fetch('SEED_GOOGLE_APIS_TOKEN', nil)
20
+ Nexo::Token.create!(
21
+ integration:,
22
+ secret: ENV.fetch('SEED_GOOGLE_APIS_TOKEN'),
23
+ tpt_status: :active,
24
+ environment: "development"
25
+ )
26
+ end
27
+ end
3
28
  end
data/lib/nexo/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # :nocov: non-viable
2
2
  module Nexo
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.4"
4
4
  end
5
5
  # :nocov:
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nexo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martín Rosso
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-05-21 00:00:00.000000000 Z
11
+ date: 2025-05-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails