multiwoven-integrations 0.21.1 → 0.22.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf7259493817f0cca526b9d359e0da09e1f0eb456754e58146757525b6e6bc9e
4
- data.tar.gz: 574b93581eadef82ac5dcf39b041e6e8ddecd5cc781a9cef28bd766393d172c2
3
+ metadata.gz: feddaa25cfb2b95c966a45eeb01792d0075160f5c33543643ab84c673dd30f69
4
+ data.tar.gz: 3b3d44540b0297276bee0476d1899a9d1c789e87e31a5313a2f07b3e35e20781
5
5
  SHA512:
6
- metadata.gz: 295d86c051f4b723acb2719f0cd14e6f7a7d01425f1246608b76a55385e24293dab399dca7350da5c45d4d8d4a92bcfcb291c0628e3a01fb6283de2b7aef119e
7
- data.tar.gz: 78a203a13c867d6df522608032bcd4b6bf8f0c318988b5db341d2ef1158c29917acf60023c522c0afb9ef1d5b75257150b0fa4168d32011369aef98a56820049
6
+ metadata.gz: aead5c7ae75014c28f31d8cfb5edf0062b4c9a630b985cd00f8ac3cc0bdf6d40414d7d06e5b8b055f463cf06b92b5f80a7934eed377dd48cf9c336ea5a508065
7
+ data.tar.gz: 97e0dc9fec590ee2208d79a52b05a6b94d7fc40690ffeb216f3fec72f0b0685307ea5f4c99d2fb2526a80de481641215829155051268a384569e06cce8a111c8
@@ -60,6 +60,8 @@ module Multiwoven
60
60
  WATSONX_GENERATION_DEPLOYMENT_URL = "https://%<region>s.ml.cloud.ibm.com/ml/v1/deployments/%<deployment_id>s/text/generation?version=%<version>s"
61
61
  WATSONX_STREAM_DEPLOYMENT_URL = "https://%<region>s.ml.cloud.ibm.com/ml/v1/deployments/%<deployment_id>s/text/generation_stream?version=%<version>s"
62
62
 
63
+ WATSONX_DATA_QUERIES_URL = "https://%<region>s.lakehouse.cloud.ibm.com/lakehouse/api/v2/queries/execute/%<engine_id>s"
64
+
63
65
  # HTTP
64
66
  HTTP_GET = "GET"
65
67
  HTTP_POST = "POST"
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Multiwoven
4
4
  module Integrations
5
- VERSION = "0.21.1"
5
+ VERSION = "0.22.0"
6
6
 
7
7
  ENABLED_SOURCES = %w[
8
8
  Snowflake
@@ -23,6 +23,7 @@ module Multiwoven
23
23
  OpenAI
24
24
  Sftp
25
25
  WatsonxAi
26
+ WatsonxData
26
27
  Anthropic
27
28
  ].freeze
28
29
 
@@ -5,7 +5,7 @@
5
5
  "connector_type": "source",
6
6
  "category": "AI Model",
7
7
  "documentation_url": "https://docs.mutltiwoven.com",
8
- "github_issue_label": "source-antropic-model",
8
+ "github_issue_label": "source-anthropic-model",
9
9
  "icon": "icon.svg",
10
10
  "license": "MIT",
11
11
  "release_stage": "alpha",
@@ -1,5 +1,5 @@
1
1
  {
2
- "documentation_url": "https://docs.multiwoven.com/integrations/source/antropic-model",
2
+ "documentation_url": "https://docs.multiwoven.com/integrations/source/anthropic-model",
3
3
  "stream_type": "user_defined",
4
4
  "connector_query_type": "ai_ml",
5
5
  "connection_specification": {
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Multiwoven::Integrations::Source
4
+ module WatsonxData
5
+ include Multiwoven::Integrations::Core
6
+ API_VERSION = "2021-05-01"
7
+ class Client < SourceConnector
8
+ def check_connection(connection_config)
9
+ create_connection(connection_config)
10
+ response = execute_query(connection_config, "show catalogs")
11
+ success?(response) ? success_status : failure_status(nil)
12
+ rescue StandardError => e
13
+ handle_exception(e, { context: "WATSONX DATA:CHECK_CONNECTION:EXCEPTION", type: "error" })
14
+ failure_status(e)
15
+ end
16
+
17
+ def discover(connection_config)
18
+ query = "SELECT table_name, column_name,
19
+ data_type,
20
+ is_nullable
21
+ FROM information_schema.columns
22
+ WHERE table_schema = '#{connection_config[:schema]}' AND table_catalog = '#{connection_config[:database]}'
23
+ ORDER BY table_name, ordinal_position"
24
+ response = execute_query(connection_config, query)
25
+ records = JSON.parse(response.body)["response"]["result"]
26
+ catalog = Catalog.new(streams: create_streams(records))
27
+ catalog.to_multiwoven_message
28
+ rescue StandardError => e
29
+ handle_exception(e, { context: "WATSONX DATA:DISCOVER:EXCEPTION", type: "error" })
30
+ end
31
+
32
+ def read(sync_config)
33
+ connection_config = sync_config.source.connection_specification
34
+ connection_config = connection_config.with_indifferent_access
35
+ query = sync_config.model.query
36
+ if connection_config[:engine] == "presto"
37
+ query = batched_query_for_presto(query, sync_config.limit, sync_config.offset) unless sync_config.limit.nil? && sync_config.offset.nil?
38
+ else
39
+ query = batched_query(query, sync_config.limit, sync_config.offset) unless sync_config.limit.nil? && sync_config.offset.nil?
40
+ end
41
+ query(connection_config, query)
42
+ rescue StandardError => e
43
+ handle_exception(e, { context: "WATSONX DATA:READ:EXCEPTION", type: "error" })
44
+ end
45
+
46
+ private
47
+
48
+ def batched_query_for_presto(query, limit, offset)
49
+ <<~SQL
50
+ SELECT * FROM (
51
+ SELECT *, ROW_NUMBER() OVER () as rownum FROM ( #{query} ) subquery
52
+ ) t
53
+ WHERE rownum > #{offset}
54
+ LIMIT #{limit}
55
+ SQL
56
+ end
57
+
58
+ def execute_query(connection_config, query)
59
+ connection_config.with_indifferent_access
60
+ get_access_token(connection_config[:api_key])
61
+ url = format(
62
+ WATSONX_DATA_QUERIES_URL,
63
+ region: connection_config[:region],
64
+ engine_id: connection_config[:engine_id]
65
+ )
66
+ headers = auth_headers(@access_token)
67
+ headers["AuthInstanceId"] = connection_config[:auth_instance_id]
68
+ send_request(
69
+ url: url,
70
+ http_method: HTTP_POST,
71
+ payload: {
72
+ sql_string: query,
73
+ catalog_name: connection_config[:database],
74
+ schema_name: connection_config[:schema]
75
+ },
76
+ headers: headers,
77
+ config: connection_config[:config]
78
+ )
79
+ end
80
+
81
+ def query(connection, query)
82
+ response = execute_query(connection, query)
83
+ response = JSON.parse(response.body).with_indifferent_access
84
+ records = response[:response][:result]
85
+ records.map do |row|
86
+ RecordMessage.new(data: row, emitted_at: Time.now.to_i).to_multiwoven_message
87
+ end
88
+ end
89
+
90
+ def create_connection(connection_config)
91
+ connection_config
92
+ end
93
+
94
+ def create_streams(records)
95
+ group_by_table(records).map do |r|
96
+ Multiwoven::Integrations::Protocol::Stream.new(name: r[:tablename], action: StreamAction["fetch"], json_schema: convert_to_json_schema(r[:columns]))
97
+ end
98
+ end
99
+
100
+ def group_by_table(records)
101
+ records.group_by { |entry| entry["table_name"] }.map do |table_name, columns|
102
+ {
103
+ tablename: table_name,
104
+ columns: columns.map do |column|
105
+ {
106
+ column_name: column["column_name"],
107
+ type: column["data_type"],
108
+ optional: column["is_nullable"] == "YES"
109
+ }
110
+ end
111
+ }
112
+ end
113
+ end
114
+
115
+ def get_access_token(api_key)
116
+ cache = defined?(Rails) && Rails.respond_to?(:cache) ? Rails.cache : ActiveSupport::Cache::MemoryStore.new
117
+ cache_key = "watsonx_data_#{api_key}"
118
+ cached_token = cache.read(cache_key)
119
+ if cached_token
120
+ @access_token = cached_token
121
+ else
122
+ new_token = get_iam_token(api_key)
123
+ # puts new_token
124
+ # max expiration is 3 minutes. No way to make it higher
125
+ cache.write(cache_key, new_token, expires_in: 180)
126
+ @access_token = new_token
127
+ end
128
+ end
129
+
130
+ def get_iam_token(api_key)
131
+ uri = URI("https://iam.cloud.ibm.com/identity/token")
132
+ request = Net::HTTP::Post.new(uri)
133
+ request["Content-Type"] = "application/x-www-form-urlencoded"
134
+ request.body = "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey=#{api_key}"
135
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
136
+ http.request(request)
137
+ end
138
+
139
+ raise "Failed to get IAM token: #{response.body}" unless response.is_a?(Net::HTTPSuccess)
140
+
141
+ JSON.parse(response.body)["access_token"]
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,16 @@
1
+ {
2
+ "data": {
3
+ "name": "WatsonxData",
4
+ "title": "WatsonX Data Endpoint",
5
+ "connector_type": "source",
6
+ "category": "Data Warehouse",
7
+ "documentation_url": "https://docs.mutltiwoven.com",
8
+ "github_issue_label": "source-watsonx-data-endpoint",
9
+ "icon": "icon.svg",
10
+ "license": "MIT",
11
+ "release_stage": "alpha",
12
+ "support_level": "community",
13
+ "tags": ["language:ruby", "multiwoven"]
14
+ }
15
+ }
16
+
@@ -0,0 +1,72 @@
1
+ {
2
+ "documentation_url": "https://docs.multiwoven.com/integrations/source/watsonx-data-endpoint",
3
+ "stream_type": "dynamic",
4
+ "connector_query_type": "raw_sql",
5
+ "connection_specification": {
6
+ "$schema": "http://json-schema.org/draft-07/schema#",
7
+ "title": "WatsonX Data Endpoint",
8
+ "type": "object",
9
+ "required": ["api_key","region","engine","engine_id","auth_instance_id","database","schema"],
10
+ "properties": {
11
+ "api_key": {
12
+ "type": "string",
13
+ "multiwoven_secret": true,
14
+ "title": "API Key",
15
+ "order": 0
16
+ },
17
+ "region": {
18
+ "description": "WatsonX Data region",
19
+ "type": "string",
20
+ "title": "Region",
21
+ "order": 1
22
+ },
23
+ "engine": {
24
+ "description": "Which engine is being used? (Presto/Spark)",
25
+ "type": "string",
26
+ "title": "Engine",
27
+ "enum": ["presto"],
28
+ "default": "presto",
29
+ "order": 2
30
+ },
31
+ "engine_id": {
32
+ "description": "Engine id",
33
+ "type": "string",
34
+ "title": "Engine Id",
35
+ "order": 3
36
+ },
37
+ "auth_instance_id": {
38
+ "description": "WatsonX Data Instance CRN",
39
+ "type": "string",
40
+ "title": "Instance CRN",
41
+ "order": 4
42
+ },
43
+ "database": {
44
+ "description": "The specific database to connect to.",
45
+ "type": "string",
46
+ "title": "Database",
47
+ "order": 5
48
+ },
49
+ "schema": {
50
+ "description": "The schema within the database.",
51
+ "type": "string",
52
+ "title": "Schema",
53
+ "order": 6
54
+ },
55
+ "config": {
56
+ "title": "",
57
+ "type": "object",
58
+ "properties": {
59
+ "timeout": {
60
+ "type": "string",
61
+ "default": "30",
62
+ "title": "HTTP Timeout",
63
+ "description": "The maximum time, in seconds, to wait for a response from the server before the request is canceled.",
64
+ "order": 0
65
+ }
66
+ },
67
+ "order": 7
68
+ }
69
+ }
70
+ }
71
+ }
72
+
@@ -0,0 +1 @@
1
+ <svg id="Watsonx-Data--Streamline-Carbon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" height="16" width="16"><desc>Watsonx Data Streamline Icon: https://streamlinehq.com</desc><defs></defs><path d="M26 24c-1.1046 0-2 .8954-2 2 0 .0764.0142.1488.0225.2229C21.7417 28.0192 18.9433 29 16 29c-2.7746 0-5.3432-.881-7.4566-2.3676.2576.0261.517.0444.7798.0444C13.5561 26.6768 17 23.233 17 19h-2c0 3.1304-2.5464 5.6768-5.6768 5.6768-2.2111 0-4.1977-1.2816-5.1318-3.2725-.1365-.2972-.2595-.6007-.3738-.9094C4.4778 20.8169 5.2174 21 6 21c2.7568 0 5-2.2432 5-5v-2H9v2c0 1.6543-1.3457 3-3 3s-3-1.3457-3-3c0-2.1152.4917-4.1328 1.4619-5.9956l-1.7744-.9238C1.5835 11.2017 1 13.5943 1 16c0 8.271 6.729 15 15 15 3.3744 0 6.5818-1.1193 9.2048-3.1662.244.106.5123.1662.7952.1662 1.1046 0 2-.8954 2-2s-.8954-2-2-2Z" fill="#000000"></path><path transform="rotate(90 22 22)" d="M21 21h2v2h-2Z" fill="#000000"></path><path transform="rotate(90 16 16)" d="M15 15h2v2h-2Z" fill="#000000"></path><path transform="rotate(-90 10 10)" d="M9 9h2v2H9Z" fill="#000000"></path><path d="M16 1c-3.3744 0-6.5818 1.1193-9.2048 3.1662C6.5512 4.0602 6.2829 4 6 4c-1.1046 0-2 .8954-2 2s.8954 2 2 2 2-.8954 2-2c0-.0764-.0142-.1488-.0225-.2229C10.2583 3.9808 13.0567 3 16 3c2.7708 0 5.3363.8784 7.4481 2.3613-.249-.0242-.5005-.038-.7547-.038-4.2329 0-7.6768 3.4438-7.6768 7.6768h2c0-3.1304 2.5464-5.6768 5.6768-5.6768 2.0554 0 3.9068 1.0953 4.9186 2.8651.2153.4283.4053.8701.5729 1.3237C27.5234 11.1887 26.7844 11 26 11c-2.7568 0-5 2.2432-5 5v2h2v-2c0-1.6543 1.3457-3 3-3s3 1.3457 3 3c0 2.1152-.4917 4.1328-1.4619 5.9956l1.7744.9238C30.4165 20.7983 31 18.4057 31 16c0-8.271-6.729-15-15-15Z" fill="#000000"></path><path id="_Transparent_Rectangle_" d="M0 0h32v32H0Z" fill="none"></path></svg>
@@ -76,6 +76,7 @@ require_relative "integrations/source/http_model/client"
76
76
  require_relative "integrations/source/open_ai/client"
77
77
  require_relative "integrations/source/sftp/client"
78
78
  require_relative "integrations/source/watsonx_ai/client"
79
+ require_relative "integrations/source/watsonx_data/client"
79
80
  require_relative "integrations/source/anthropic/client"
80
81
 
81
82
  # Destination
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.21.1
4
+ version: 0.22.0
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: 2025-03-20 00:00:00.000000000 Z
11
+ date: 2025-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -786,6 +786,10 @@ files:
786
786
  - lib/multiwoven/integrations/source/watsonx_ai/config/meta.json
787
787
  - lib/multiwoven/integrations/source/watsonx_ai/config/spec.json
788
788
  - lib/multiwoven/integrations/source/watsonx_ai/icon.svg
789
+ - lib/multiwoven/integrations/source/watsonx_data/client.rb
790
+ - lib/multiwoven/integrations/source/watsonx_data/config/meta.json
791
+ - lib/multiwoven/integrations/source/watsonx_data/config/spec.json
792
+ - lib/multiwoven/integrations/source/watsonx_data/icon.svg
789
793
  - multiwoven-integrations.gemspec
790
794
  - sig/multiwoven/integrations.rbs
791
795
  homepage: https://www.multiwoven.com/