multiwoven-integrations 0.1.36 → 0.1.37

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: 818c8606d1ef1b50bd14765b3ed85f687ef5e16cdd975324bfbf28ed2b371070
4
- data.tar.gz: 0bd41ef2fe575ff51d5ea5878522509de3aa6ae0b3592074c15ce3de5be97c51
3
+ metadata.gz: 13fe187a421657cfb45280d87ae9fdd88dfb57b684290aba50869fc73bbd19c2
4
+ data.tar.gz: 8d08feb79f2798e6955c482af4ec2ecaccc35ff723d60191c6efcfc85f173972
5
5
  SHA512:
6
- metadata.gz: dfaa4c53e72fbf3fc64d2d746bf4fd632c19be834af900a93eb88060fc1a84156b1849b645768ca41ebd3037f205a7b4f79430738eddb7f607b526fb9424c08b
7
- data.tar.gz: dd7dc877f6ad86082975cb9dbdc714bc5e9dc623196178e6c9c11b601deab967fa107d1d218d5dc03e43b6b6c580403d45bc470fd364a109a8a1cb6e8a793520
6
+ metadata.gz: b828ceef6251ca0859da2c5fe74e763c2a3f366cd461839456b74d4791eec94e482d7cfa1673ff76511f3e48dc8e7d09a0b216ff2f8a47585ff69cb628745a96
7
+ data.tar.gz: 639488c9e265492f3e98b69cfd5010998c569a99c70bb11f2cbfbed92499f7b4c2eacf4f2febe0698cafebc6d039f3e18834eb6e8d010ff137f9603ac060ce6e
@@ -3,8 +3,6 @@
3
3
  module Multiwoven
4
4
  module Integrations::Core
5
5
  class DestinationConnector < BaseConnector
6
- prepend RateLimiter
7
-
8
6
  # Records are transformed json payload send it to the destination
9
7
  # SyncConfig is the Protocol::SyncConfig object
10
8
  def write(_sync_config, _records, _action = "insert")
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Multiwoven
4
+ module Integrations::Core
5
+ module Fullrefresher
6
+ def write(sync_config, records, action = "insert")
7
+ if sync_config && sync_config.sync_mode == "full_refresh" && !@full_refreshed
8
+ response = clear_all_records(sync_config)
9
+ return response unless response &&
10
+ response.control.status == Multiwoven::Integrations::Protocol::ConnectionStatusType["succeeded"]
11
+
12
+ @full_refreshed = true
13
+ end
14
+
15
+ super(sync_config, records, action)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -7,6 +7,7 @@ module Multiwoven
7
7
  module Airtable
8
8
  include Multiwoven::Integrations::Core
9
9
  class Client < DestinationConnector # rubocop:disable Metrics/ClassLength
10
+ prepend Multiwoven::Integrations::Core::RateLimiter
10
11
  MAX_CHUNK_SIZE = 10
11
12
  def check_connection(connection_config)
12
13
  connection_config = connection_config.with_indifferent_access
@@ -4,6 +4,7 @@ module Multiwoven::Integrations::Destination
4
4
  module FacebookCustomAudience
5
5
  include Multiwoven::Integrations::Core
6
6
  class Client < DestinationConnector # rubocop:disable Metrics/ClassLength
7
+ prepend Multiwoven::Integrations::Core::RateLimiter
7
8
  MAX_CHUNK_SIZE = 10_000
8
9
  def check_connection(connection_config)
9
10
  connection_config = connection_config.with_indifferent_access
@@ -33,7 +33,7 @@
33
33
  "PAGEUID": { "type": ["string", "null"], "default": null, "title": "Page-Scoped ID", "x-hashRequired": false }
34
34
  }
35
35
  },
36
- "supported_sync_modes": ["full_refresh", "incremental"],
36
+ "supported_sync_modes": ["incremental"],
37
37
  "source_defined_cursor": true,
38
38
  "default_cursor_field": ["updated"],
39
39
  "source_defined_primary_key": [["email"]]
@@ -7,9 +7,12 @@ module Multiwoven
7
7
  include Multiwoven::Integrations::Core
8
8
 
9
9
  class Client < DestinationConnector # rubocop:disable Metrics/ClassLength
10
+ prepend Multiwoven::Integrations::Core::Fullrefresher
11
+ prepend Multiwoven::Integrations::Core::RateLimiter
10
12
  MAX_CHUNK_SIZE = 10_000
11
13
 
12
14
  def check_connection(connection_config)
15
+ connection_config = connection_config.with_indifferent_access
13
16
  authorize_client(connection_config)
14
17
  fetch_google_spread_sheets(connection_config)
15
18
  success_status
@@ -19,6 +22,7 @@ module Multiwoven
19
22
  end
20
23
 
21
24
  def discover(connection_config)
25
+ connection_config = connection_config.with_indifferent_access
22
26
  authorize_client(connection_config)
23
27
  spreadsheets = fetch_google_spread_sheets(connection_config)
24
28
  catalog = build_catalog_from_spreadsheets(spreadsheets, connection_config)
@@ -34,6 +38,24 @@ module Multiwoven
34
38
  handle_exception("GOOGLE_SHEETS:CRM:WRITE:EXCEPTION", "error", e)
35
39
  end
36
40
 
41
+ def clear_all_records(sync_config)
42
+ setup_write_environment(sync_config, "clear")
43
+ connection_specification = sync_config.destination.connection_specification.with_indifferent_access
44
+ spreadsheet = fetch_google_spread_sheets(connection_specification)
45
+ sheet_ids = spreadsheet.sheets.map(&:properties).map(&:sheet_id)
46
+
47
+ delete_extra_sheets(sheet_ids)
48
+
49
+ unless sheet_ids.empty?
50
+ clear_response = clear_sheet_data(spreadsheet.sheets.first.properties.title)
51
+ return control_message("Successfully cleared data.", "succeeded") if clear_response&.cleared_range
52
+ end
53
+
54
+ control_message("Failed to clear data.", "failed")
55
+ rescue StandardError => e
56
+ control_message(e.message, "failed")
57
+ end
58
+
37
59
  private
38
60
 
39
61
  # To define the level of access granted to your app, you need to identify and declare authorization scopes which is provided by google scopse https://developers.google.com/sheets/api/scopes
@@ -99,7 +121,7 @@ module Multiwoven
99
121
  batch_support: true,
100
122
  batch_size: 10_000,
101
123
  json_schema: generate_properties_schema(column_names),
102
- supported_sync_modes: %w[incremental]
124
+ supported_sync_modes: %w[incremental full_refresh]
103
125
  }.with_indifferent_access
104
126
  end
105
127
 
@@ -113,8 +135,9 @@ module Multiwoven
113
135
 
114
136
  def setup_write_environment(sync_config, action)
115
137
  @action = sync_config.stream.action || action
116
- @spreadsheet_id = extract_spreadsheet_id(sync_config.destination.connection_specification[:spreadsheet_link])
117
- authorize_client(sync_config.destination.connection_specification)
138
+ connection_specification = sync_config.destination.connection_specification.with_indifferent_access
139
+ @spreadsheet_id = extract_spreadsheet_id(connection_specification[:spreadsheet_link])
140
+ authorize_client(connection_specification)
118
141
  end
119
142
 
120
143
  def extract_spreadsheet_id(link)
@@ -176,6 +199,31 @@ module Multiwoven
176
199
  success: success, failed: failure
177
200
  ).to_multiwoven_message
178
201
  end
202
+
203
+ def delete_extra_sheets(sheet_ids)
204
+ # Leave one sheet intact as a spreadsheet must have at least one sheet.
205
+ # Delete all other sheets.
206
+ (sheet_ids.length - 1).times do |i|
207
+ request = Google::Apis::SheetsV4::BatchUpdateSpreadsheetRequest.new(
208
+ requests: [{ delete_sheet: { sheet_id: sheet_ids[i + 1] } }]
209
+ )
210
+ @client.batch_update_spreadsheet(@spreadsheet_id, request)
211
+ end
212
+ end
213
+
214
+ def clear_sheet_data(sheet_title)
215
+ clear_request = Google::Apis::SheetsV4::ClearValuesRequest.new
216
+ @client&.clear_values(@spreadsheet_id, "#{sheet_title}!A2:Z", clear_request)
217
+ end
218
+
219
+ def control_message(message, status)
220
+ ControlMessage.new(
221
+ type: "full_refresh",
222
+ emitted_at: Time.now.to_i,
223
+ status: ConnectionStatusType[status],
224
+ meta: { detail: message }
225
+ ).to_multiwoven_message
226
+ end
179
227
  end
180
228
  end
181
229
  end
@@ -9,6 +9,7 @@ module Multiwoven
9
9
  include Multiwoven::Integrations::Core
10
10
 
11
11
  class Client < DestinationConnector
12
+ prepend Multiwoven::Integrations::Core::RateLimiter
12
13
  def check_connection(connection_config)
13
14
  connection_config = connection_config.with_indifferent_access
14
15
  initialize_client(connection_config)
@@ -4,6 +4,7 @@ module Multiwoven::Integrations::Destination
4
4
  module Klaviyo
5
5
  include Multiwoven::Integrations::Core
6
6
  class Client < DestinationConnector
7
+ prepend Multiwoven::Integrations::Core::RateLimiter
7
8
  def check_connection(connection_config)
8
9
  connection_config = connection_config.with_indifferent_access
9
10
  api_key = connection_config[:private_api_key]
@@ -11,6 +11,7 @@ module Multiwoven
11
11
  API_VERSION = "59.0"
12
12
 
13
13
  class Client < DestinationConnector
14
+ prepend Multiwoven::Integrations::Core::RateLimiter
14
15
  def check_connection(connection_config)
15
16
  connection_config = connection_config.with_indifferent_access
16
17
  initialize_client(connection_config)
@@ -7,6 +7,7 @@ module Multiwoven
7
7
  include Multiwoven::Integrations::Core
8
8
 
9
9
  class Client < DestinationConnector
10
+ prepend Multiwoven::Integrations::Core::RateLimiter
10
11
  attr_accessor :channel_id
11
12
 
12
13
  def check_connection(connection_config)
@@ -9,6 +9,7 @@ module Multiwoven
9
9
  API_VERSION = "59.0"
10
10
 
11
11
  class Client < DestinationConnector
12
+ prepend Multiwoven::Integrations::Core::RateLimiter
12
13
  def check_connection(connection_config)
13
14
  connection_config = connection_config.with_indifferent_access
14
15
  initialize_client(connection_config)
@@ -20,7 +20,7 @@ module Multiwoven
20
20
  "tracking"
21
21
  )
22
22
  ControlMessageType = Types::String.enum(
23
- "rate_limit", "connection_config"
23
+ "rate_limit", "connection_config", "full_refresh"
24
24
  )
25
25
  LogLevel = Types::String.enum("fatal", "error", "warn", "info", "debug", "trace")
26
26
  RequestRateLimitingUnit = Types::String.default("minute").enum("minute", "hour", "day")
@@ -170,6 +170,7 @@ module Multiwoven
170
170
  class ControlMessage < ProtocolModel
171
171
  attribute :type, ControlMessageType
172
172
  attribute :emitted_at, Types::Integer
173
+ attribute? :status, ConnectionStatusType.optional
173
174
  attribute? :meta, Types::Hash
174
175
 
175
176
  def to_multiwoven_message
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Multiwoven
4
4
  module Integrations
5
- VERSION = "0.1.36"
5
+ VERSION = "0.1.37"
6
6
 
7
7
  ENABLED_SOURCES = %w[
8
8
  Snowflake
@@ -29,6 +29,7 @@ require_relative "integrations/service"
29
29
  require_relative "integrations/core/constants"
30
30
  require_relative "integrations/core/utils"
31
31
  require_relative "integrations/core/rate_limiter"
32
+ require_relative "integrations/core/fullrefresher"
32
33
  require_relative "integrations/protocol/protocol"
33
34
  require_relative "integrations/core/base_connector"
34
35
  require_relative "integrations/core/source_connector"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: multiwoven-integrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.36
4
+ version: 0.1.37
5
5
  platform: ruby
6
6
  authors:
7
7
  - Subin T P
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-03-13 00:00:00.000000000 Z
11
+ date: 2024-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: google-apis-sheets_v4
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: google-cloud-bigquery
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -220,6 +234,20 @@ dependencies:
220
234
  - - ">="
221
235
  - !ruby/object:Gem::Version
222
236
  version: '0'
237
+ - !ruby/object:Gem::Dependency
238
+ name: stripe
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :runtime
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
223
251
  - !ruby/object:Gem::Dependency
224
252
  name: byebug
225
253
  requirement: !ruby/object:Gem::Requirement
@@ -326,6 +354,7 @@ files:
326
354
  - lib/multiwoven/integrations/core/base_connector.rb
327
355
  - lib/multiwoven/integrations/core/constants.rb
328
356
  - lib/multiwoven/integrations/core/destination_connector.rb
357
+ - lib/multiwoven/integrations/core/fullrefresher.rb
329
358
  - lib/multiwoven/integrations/core/http_client.rb
330
359
  - lib/multiwoven/integrations/core/rate_limiter.rb
331
360
  - lib/multiwoven/integrations/core/source_connector.rb