chroma-db 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8334143128edb78d734a0154da3432e1d8e222922341b182e1d589f91a227a3
4
- data.tar.gz: 30f9c52759742ca2848e87df649c683a683bce9a00041abb9ed91a77b746dd9a
3
+ metadata.gz: 9273343cf2f29991d61d8e5393dfd06541211c84e03769162fa984c9ca2c8620
4
+ data.tar.gz: 3dd3e94d5914e5776aef673f18b06bbb6f61254bbe4eb51ae25f8675f6c9c72b
5
5
  SHA512:
6
- metadata.gz: 41838e89fe84ef6317092a8fc604ae13ec99a2619fbb56fb18b72d2b5b837dd2fa550ebdb0e9802b6026ba487e250d5839d0417e59bcb99589137debdbec82ef
7
- data.tar.gz: 2dfd54367af2f122265a51e1e9d2e228e58b14984f4aab91e940f732f682db7ea5744fb758bb114875165b5ca907be6493d6aa3d1b68637ff79d65c07b7f62b4
6
+ metadata.gz: 8c94d838879f22cae956b9a4b7e66f8b8a8d76792770dda6eb9a91b197aa0eb3b8408256653402feb750732f35fb221ae2ebedfe05ab49d89896b80579228ed0
7
+ data.tar.gz: f5ad7421b54da9909a3a1c76d36d07738ccd44aaa934a7e960e5b102608e24c61e36243b59c0d2ba469e01c34b2cc360e2a07a82516d1a4a2d73cfffa49334fa
data/Gemfile CHANGED
@@ -12,3 +12,5 @@ gem "minitest", "~> 5.0"
12
12
  gem "standard", "~> 1.3"
13
13
 
14
14
  gem "rbs", "~> 3.1"
15
+
16
+ gem "webmock", "~> 3.18", ">= 3.18.1"
data/Gemfile.lock CHANGED
@@ -1,14 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- chroma-db (0.1.0)
4
+ chroma-db (0.2.0)
5
5
  dry-monads (~> 1.6)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
+ addressable (2.8.4)
11
+ public_suffix (>= 2.0.2, < 6.0)
10
12
  ast (2.4.2)
11
13
  concurrent-ruby (1.2.2)
14
+ crack (0.4.5)
15
+ rexml
12
16
  dry-core (1.0.0)
13
17
  concurrent-ruby (~> 1.0)
14
18
  zeitwerk (~> 2.6)
@@ -16,6 +20,7 @@ GEM
16
20
  concurrent-ruby (~> 1.0)
17
21
  dry-core (~> 1.0, < 2)
18
22
  zeitwerk (~> 2.6)
23
+ hashdiff (1.0.1)
19
24
  json (2.6.3)
20
25
  language_server-protocol (3.17.0.3)
21
26
  lint_roller (1.0.0)
@@ -23,6 +28,7 @@ GEM
23
28
  parallel (1.23.0)
24
29
  parser (3.2.2.1)
25
30
  ast (~> 2.4.1)
31
+ public_suffix (5.0.1)
26
32
  rainbow (3.1.1)
27
33
  rake (13.0.6)
28
34
  rbs (3.1.0)
@@ -56,10 +62,15 @@ GEM
56
62
  lint_roller (~> 1.0)
57
63
  rubocop-performance (~> 1.16.0)
58
64
  unicode-display_width (2.4.2)
65
+ webmock (3.18.1)
66
+ addressable (>= 2.8.0)
67
+ crack (>= 0.3.2)
68
+ hashdiff (>= 0.4.0, < 2.0.0)
59
69
  zeitwerk (2.6.8)
60
70
 
61
71
  PLATFORMS
62
72
  arm64-darwin-22
73
+ x86_64-linux
63
74
 
64
75
  DEPENDENCIES
65
76
  chroma-db!
@@ -67,6 +78,7 @@ DEPENDENCIES
67
78
  rake (~> 13.0)
68
79
  rbs (~> 3.1)
69
80
  standard (~> 1.3)
81
+ webmock (~> 3.18, >= 3.18.1)
70
82
 
71
83
  BUNDLED WITH
72
84
  2.4.12
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chroma
4
+ module APIOperations
5
+ # Request's response Data object.
6
+ #
7
+ # status - HTTP status code. It is zero when a request fails due to network error.
8
+ # body - Parsed JSON object or response body.
9
+ # headers - HTTP response headers.
10
+ # error - Exception or Net::HTTPResponse object if the response is not Net::HTTPSuccess
11
+ Response = Data.define(:status, :body, :headers, :error)
12
+
13
+ # Request module provides functionality to perform HTTP requests.
14
+ module Request
15
+ module ClassMethods
16
+ include Dry::Monads[:result]
17
+
18
+ # Execute an HTTP request and return a monad wrapping the response.
19
+ #
20
+ # method - The HTTP method to use (e.g. 'GET', 'POST'). Method must be a `Symbol`.
21
+ # url - The URL to send the request to.
22
+ # params - The query parameters or request body. Params needs to be in a form of a Hash.
23
+ # options - Additional options to pass to the request.
24
+ #
25
+ # A `Dry::Monads::Result` monad wrapping the response, either a success or failure.
26
+ # The response is a `Chroma::APIOperations::Response` Data object.
27
+ #
28
+ # Examples
29
+ #
30
+ # result = execute_request(:get, "https://example.com", {name: "test request"})
31
+ # if result.success?
32
+ # puts "Response status: #{result.success.status}"
33
+ # puts "Response body: #{result.success.body}"
34
+ # else
35
+ # puts "Request failed with error: #{result.failure.error}"
36
+ # end
37
+ def execute_request(method, url, params = {}, options = {})
38
+ uri = URI.parse(url)
39
+
40
+ request = build_request(method, uri, params)
41
+
42
+ use_ssl = options.delete(:use_ssl) || false
43
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl:) do |http|
44
+ Chroma::Util.log_debug("Sending a request", {method:, uri:, params:})
45
+ http.request(request)
46
+ end
47
+
48
+ build_response(response)
49
+ rescue => ex
50
+ build_response(ex)
51
+ end
52
+
53
+ private def build_response(response)
54
+ case response
55
+ in Net::HTTPSuccess => success_response
56
+ Chroma::Util.log_info("Successful response", code: success_response.code)
57
+
58
+ build_response_details(success_response)
59
+ in Net::HTTPRedirection => redirect_response
60
+ Chroma::Util.log_info("Server redirect response", code: redirect_response.code, location: redirect_response["location"])
61
+
62
+ build_response_details(redirect_response)
63
+ in Net::HTTPClientError => client_error_response
64
+ Chroma::Util.log_error("Client error response", code: client_error_response.code, body: client_error_response.body)
65
+
66
+ build_response_details(client_error_response)
67
+ in Net::HTTPServerError => server_error_response
68
+ Chroma::Util.log_error("Server error response", code: server_error_response.code)
69
+
70
+ build_response_details(server_error_response, parse_body: false)
71
+ else
72
+ Chroma::Util.log_error("An error happened", error: response.to_s)
73
+
74
+ build_response_details(response, exception: true, parse_body: false)
75
+ end
76
+ end
77
+
78
+ private def build_response_details(response, exception: false, parse_body: true)
79
+ response_data = Chroma::APIOperations::Response.new(
80
+ status: exception ? 0 : response.code.to_i,
81
+ body: if exception
82
+ exception.to_s
83
+ else
84
+ (parse_body ? body_to_json(response.body) : response.body)
85
+ end,
86
+ headers: exception ? {} : response.each_header.to_h,
87
+ error: response.is_a?(Net::HTTPSuccess) ? nil : response
88
+ )
89
+
90
+ case response
91
+ in Net::HTTPSuccess
92
+ return Success(response_data)
93
+ else
94
+ return Failure(response_data)
95
+ end
96
+ end
97
+
98
+ private def body_to_json(content)
99
+ JSON.parse(content, symbolize_keys: true)
100
+ rescue JSON::ParserError, TypeError
101
+ content
102
+ end
103
+
104
+ private def build_request(method, uri, params)
105
+ request = case method
106
+ when :post then Net::HTTP::Post.new(uri)
107
+ when :put then Net::HTTP::Put.new(uri)
108
+ when :delete then Net::HTTP::Delete.new(uri)
109
+ else
110
+ Net::HTTP::Get.new(uri)
111
+ end
112
+
113
+ request.content_type = "application/json"
114
+ request.body = params.to_json if params.size > 0
115
+
116
+ request
117
+ end
118
+ end
119
+
120
+ def self.included(base)
121
+ base.extend(ClassMethods)
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chroma
4
+ # map to the same values as the standard library's logger
5
+ LEVEL_DEBUG = Logger::DEBUG
6
+ LEVEL_ERROR = Logger::ERROR
7
+ LEVEL_INFO = Logger::INFO
8
+
9
+ @config = Chroma::ChromaConfiguration.setup
10
+
11
+ class << self
12
+ extend Forwardable
13
+
14
+ attr_reader :config
15
+
16
+ # User configuration options
17
+ def_delegators :@config, :connect_host, :connect_host=
18
+ def_delegators :@config, :api_base, :api_base=
19
+ def_delegators :@config, :api_version, :api_version=
20
+ def_delegators :@config, :log_level, :log_level=
21
+ def_delegators :@config, :logger, :logger=
22
+ end
23
+
24
+ def self.api_url
25
+ "#{connect_host}/#{api_base}/#{api_version}"
26
+ end
27
+
28
+ Chroma.log_level = ENV["CHROMA_LOG"].to_i unless ENV["CHROMA_LOG"].nil?
29
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chroma
4
+ # The ChromaConfiguration class allows you to configure the connection settings for a Chroma service client.
5
+ # It can be initialized directly calling #new method.
6
+ #
7
+ # Examples
8
+ #
9
+ # configuration = Chroma::ChromaConfiguration.new
10
+ # configurarion.connect_host = "https://chroma.example.com"
11
+ #
12
+ # Or via a setup block.
13
+ #
14
+ # Examples
15
+ #
16
+ # Chroma::ChromaConfiguration.setup do |config|
17
+ # config.connect_host = "https://chroma.example.com"
18
+ # end
19
+ class ChromaConfiguration
20
+ # Sets the host name for the Chroma service.
21
+ #
22
+ # Examples
23
+ #
24
+ # config.connect_host = "chroma.example.com"
25
+ #
26
+ # Returns the String host name.
27
+ attr_accessor :connect_host
28
+
29
+ # Sets the base path for the Chroma API.
30
+ #
31
+ # Examples
32
+ #
33
+ # config.api_base = "/api"
34
+ #
35
+ # Returns the String API base path.
36
+ attr_accessor :api_base
37
+ # Sets the version of the Chroma API.
38
+ #
39
+ # Examples
40
+ #
41
+ # config.api_version = "v1"
42
+ #
43
+ # Returns the String API version.
44
+ attr_accessor :api_version
45
+ # Sets the logger for the Chroma service client.
46
+ #
47
+ # Examples
48
+ #
49
+ # config.logger = Logger.new(STDOUT)
50
+ #
51
+ # Returns the Logger instance.
52
+ attr_accessor :logger
53
+ # Sets the logger's log level for the Chroma service client.
54
+ #
55
+ # Examples
56
+ #
57
+ # config.log_level = Chroma::LEVEL_INFO
58
+ #
59
+ # Returns the log level constant
60
+ attr_accessor :log_level
61
+
62
+ def self.setup
63
+ new.tap do |instance|
64
+ yield(instance) if block_given?
65
+ end
66
+ end
67
+
68
+ def initialize
69
+ @api_base = "api"
70
+ @api_version = "v1"
71
+
72
+ @log_level = Chroma::LEVEL_INFO
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Chroma
4
+ # ChromaError is the base error from which all other more specific Chrome
5
+ # errors derive.
6
+ class ChromaError < StandardError
7
+ attr_accessor :response
8
+
9
+ attr_reader :message
10
+ attr_reader :error
11
+ attr_reader :body
12
+ attr_reader :status
13
+
14
+ def initialize(message = nil, status: nil, body: nil, response: nil)
15
+ @message = message
16
+ @status = status
17
+ @body = body
18
+ @response = response
19
+ end
20
+
21
+ def to_s
22
+ status_value = @status.nil? ? "" : "(Status #{@status}) "
23
+ "#{status_value}#{@message}"
24
+ end
25
+ end
26
+
27
+ # APIConnectionError is raised in the event that the SDK can't connect to
28
+ # Chroma's database. That can be for a variety of different reasons from a
29
+ # downed network to a bad TLS certificate.
30
+ class APIConnectionError < ChromaError
31
+ end
32
+
33
+ # InvalidRequestError is raised when a request is initiated with invalid
34
+ # parameters.
35
+ class InvalidRequestError < ChromaError
36
+ def initialize(message = nil, status: nil, body: nil, response: nil)
37
+ super
38
+
39
+ decode_message
40
+ end
41
+
42
+ private
43
+
44
+ def decode_message
45
+ if message.include?("ValueError")
46
+ error = JSON.parse(message)
47
+ value = error.fetch("error", "").sub("ValueError('", "").sub("')", "")
48
+ @message = value if !value.nil?
49
+ end
50
+ rescue JSON::ParserError, TypeError
51
+ end
52
+ end
53
+
54
+ # APIError is a generic error that may be raised in cases where none of the
55
+ # other named errors cover the problem.
56
+ class APIError < ChromaError
57
+ def initialize(message = nil, status: nil, body: nil, response: nil)
58
+ super
59
+
60
+ decode_message
61
+ end
62
+
63
+ private
64
+
65
+ def decode_message
66
+ if message.is_a?(Hash) && message.has_key?("error")
67
+ @message = message.fetch("error")
68
+ end
69
+ end
70
+ end
71
+ end