qdrant-ruby 0.9.10 → 0.10.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: 6269ed0349b2612a9221b36a181df8c4126e4542685b313dcf839cfc5a91314a
4
- data.tar.gz: 660452185073d98c71d11ebe68b18dd5c0b16ee96085d830896529a618f473e9
3
+ metadata.gz: 0207e687f622cdcf258c493bb8b75c783c9847574abe41fcf4489f93ba40752c
4
+ data.tar.gz: 48df2d6de390314ff6d6b18f2d155d118c81c417d8f21c2032ce2681094945b8
5
5
  SHA512:
6
- metadata.gz: 7b4b80c0d1867ca65b7710974f6c13dd5e885b84b8ded38a2c34499ecff63ed3fdf782fa35a892ea32a110b3448a3b49b61e8f5e1dd7cd2f3ff946065c7ea80a
7
- data.tar.gz: 8c4957ff10a42198a4f0a133323c99d197eec8177e5c3daec7b1d708255ce101c1b5e4b9e3a70b0fc7e11ac7bda2da15b15a312932875ba36d556468e08527ad
6
+ metadata.gz: 65b92ac01bc6346e03f1a4ce928292a5ce4ed0eff4fc36083199b2d6db3b096a9b9a9ca2e07de0d2936490e83b338c3ce0d2d70bafd60a8617aa20aa438c43c5
7
+ data.tar.gz: f301dd5bc6d3014af75ee6ae9916937b2324ab7abd444199b3c7ba843c8192ad1c610fb827183894e597c61552e81695d1b78f8674353c541521485213296439
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.10.0] - 2026-08-12
4
+ - Drop Faraday dependency
5
+
6
+ ## [0.9.10] - 2025-11-23
7
+
3
8
  ## [0.9.9] - 2024-04-11
4
9
  - Allow sparse_vectors to be passed to collections.create
5
10
  - Support query endpoint
@@ -14,7 +19,8 @@
14
19
  - Updated Points#delete() method: Removed the requirement to specify points: in parameters. Now generates an error if neither points: nor filters: are provided, aligning with delete_points documentation standards.
15
20
 
16
21
  ## [0.9.5] - 2024-01-12
17
- - Bugfix: ArgumentError for filter in points delete
22
+ - Bugfix: ArgumentError for filter in points delete
23
+
18
24
  ## [0.9.4] - 2023-08-31
19
25
  - Introduce `Points#get_all()` method
20
26
 
data/Gemfile CHANGED
@@ -5,7 +5,7 @@ source "https://rubygems.org"
5
5
  # Specify your gem's dependencies in qdrant.gemspec
6
6
  gemspec
7
7
 
8
- gem "rake", "~> 13.3"
8
+ gem "rake", "~> 13.4"
9
9
 
10
10
  gem "rspec", "~> 3.13"
11
- gem "standard", "~> 1.28.5"
11
+ gem "standard", "~> 1.56.0"
data/Gemfile.lock CHANGED
@@ -1,41 +1,41 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- qdrant-ruby (0.9.10)
5
- faraday (>= 2.0.1, < 3)
4
+ qdrant-ruby (0.10.0)
5
+ logger
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
- ast (2.4.2)
11
- base64 (0.2.0)
12
- byebug (11.1.3)
10
+ ast (2.4.3)
11
+ byebug (13.0.0)
12
+ reline (>= 0.6.0)
13
13
  coderay (1.1.3)
14
14
  diff-lcs (1.6.2)
15
- faraday (2.8.1)
16
- base64
17
- faraday-net_http (>= 2.0, < 3.1)
18
- ruby2_keywords (>= 0.0.4)
19
- faraday-net_http (3.0.2)
20
- json (2.7.4)
21
- language_server-protocol (3.17.0.3)
15
+ io-console (0.9.2)
16
+ json (2.21.2)
17
+ language_server-protocol (3.17.0.6)
22
18
  lint_roller (1.1.0)
23
- method_source (1.0.0)
24
- parallel (1.24.0)
25
- parser (3.3.5.0)
19
+ logger (1.7.0)
20
+ method_source (1.1.0)
21
+ parallel (2.1.0)
22
+ parser (3.3.12.0)
26
23
  ast (~> 2.4.1)
27
24
  racc
28
- pry (0.14.2)
25
+ prism (1.9.0)
26
+ pry (0.16.0)
29
27
  coderay (~> 1.1)
30
28
  method_source (~> 1.0)
31
- pry-byebug (3.10.1)
32
- byebug (~> 11.0)
33
- pry (>= 0.13, < 0.15)
29
+ reline (>= 0.6.0)
30
+ pry-byebug (3.12.0)
31
+ byebug (~> 13.0)
32
+ pry (>= 0.13, < 0.17)
34
33
  racc (1.8.1)
35
34
  rainbow (3.1.1)
36
- rake (13.3.1)
37
- regexp_parser (2.9.2)
38
- rexml (3.4.2)
35
+ rake (13.4.2)
36
+ regexp_parser (2.12.0)
37
+ reline (0.7.0)
38
+ io-console (~> 0.5)
39
39
  rspec (3.13.2)
40
40
  rspec-core (~> 3.13.0)
41
41
  rspec-expectations (~> 3.13.0)
@@ -45,40 +45,44 @@ GEM
45
45
  rspec-expectations (3.13.5)
46
46
  diff-lcs (>= 1.2.0, < 2.0)
47
47
  rspec-support (~> 3.13.0)
48
- rspec-mocks (3.13.6)
48
+ rspec-mocks (3.13.8)
49
49
  diff-lcs (>= 1.2.0, < 2.0)
50
50
  rspec-support (~> 3.13.0)
51
- rspec-support (3.13.6)
52
- rubocop (1.50.2)
51
+ rspec-support (3.13.7)
52
+ rubocop (1.88.2)
53
53
  json (~> 2.3)
54
- parallel (~> 1.10)
55
- parser (>= 3.2.0.0)
54
+ language_server-protocol (~> 3.17.0.2)
55
+ lint_roller (~> 1.1.0)
56
+ parallel (>= 1.10)
57
+ parser (>= 3.3.0.2)
56
58
  rainbow (>= 2.2.2, < 4.0)
57
- regexp_parser (>= 1.8, < 3.0)
58
- rexml (>= 3.2.5, < 4.0)
59
- rubocop-ast (>= 1.28.0, < 2.0)
59
+ regexp_parser (>= 2.9.3, < 3.0)
60
+ rubocop-ast (>= 1.49.0, < 2.0)
60
61
  ruby-progressbar (~> 1.7)
61
- unicode-display_width (>= 2.4.0, < 3.0)
62
- rubocop-ast (1.30.0)
63
- parser (>= 3.2.1.0)
64
- rubocop-performance (1.16.0)
65
- rubocop (>= 1.7.0, < 2.0)
66
- rubocop-ast (>= 0.4.0)
62
+ unicode-display_width (>= 2.4.0, < 4.0)
63
+ rubocop-ast (1.50.0)
64
+ parser (>= 3.3.7.2)
65
+ prism (~> 1.7)
66
+ rubocop-performance (1.26.1)
67
+ lint_roller (~> 1.1)
68
+ rubocop (>= 1.75.0, < 2.0)
69
+ rubocop-ast (>= 1.47.1, < 2.0)
67
70
  ruby-progressbar (1.13.0)
68
- ruby2_keywords (0.0.5)
69
- standard (1.28.5)
71
+ standard (1.56.0)
70
72
  language_server-protocol (~> 3.17.0.2)
71
73
  lint_roller (~> 1.0)
72
- rubocop (~> 1.50.2)
74
+ rubocop (~> 1.88.0)
73
75
  standard-custom (~> 1.0.0)
74
- standard-performance (~> 1.0.1)
76
+ standard-performance (~> 1.8)
75
77
  standard-custom (1.0.2)
76
78
  lint_roller (~> 1.0)
77
79
  rubocop (~> 1.50)
78
- standard-performance (1.0.1)
79
- lint_roller (~> 1.0)
80
- rubocop-performance (~> 1.16.0)
81
- unicode-display_width (2.6.0)
80
+ standard-performance (1.9.0)
81
+ lint_roller (~> 1.1)
82
+ rubocop-performance (~> 1.26.0)
83
+ unicode-display_width (3.2.0)
84
+ unicode-emoji (~> 4.1)
85
+ unicode-emoji (4.2.0)
82
86
 
83
87
  PLATFORMS
84
88
  arm64-darwin-23
@@ -90,9 +94,9 @@ PLATFORMS
90
94
  DEPENDENCIES
91
95
  pry-byebug (~> 3.9)
92
96
  qdrant-ruby!
93
- rake (~> 13.3)
97
+ rake (~> 13.4)
94
98
  rspec (~> 3.13)
95
- standard (~> 1.28.5)
99
+ standard (~> 1.56.0)
96
100
 
97
101
  BUNDLED WITH
98
- 2.4.0
102
+ 2.5.3
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Qdrant
2
2
 
3
3
  <p>
4
- <img alt='Qdrant logo' src='https://qdrant.tech/images/logo_with_text.svg' height='50' />
4
+ <img alt='Qdrant logo' src='https://qdrant.tech/img/brand-resources-logos/qdrant-brandmark-red.svg' height='50' />
5
5
  &nbsp;&nbsp;+&nbsp;&nbsp;
6
6
  <img alt='Ruby logo' src='https://user-images.githubusercontent.com/541665/230231593-43861278-4550-421d-a543-fd3553aac4f6.png' height='40' />
7
7
  </p>
@@ -13,7 +13,7 @@ Part of the [Langchain.rb](https://github.com/andreibondarev/langchainrb) stack.
13
13
  ![Tests status](https://github.com/andreibondarev/qdrant-ruby/actions/workflows/ci.yml/badge.svg)
14
14
  [![Gem Version](https://badge.fury.io/rb/qdrant-ruby.svg)](https://badge.fury.io/rb/qdrant-ruby)
15
15
  [![Docs](http://img.shields.io/badge/yard-docs-blue.svg)](http://rubydoc.info/gems/qdrant-ruby)
16
- [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/andreibondarev/qdrant-ruby/blob/main/LICENSE.txt)
16
+ [![License](https://img.shields.io/badge/license-Apache2.0-green.svg)](https://github.com/andreibondarev/qdrant-ruby/blob/main/LICENSE.txt)
17
17
  [![](https://dcbadge.vercel.app/api/server/WDARp7J2n8?compact=true&style=flat)](https://discord.gg/WDARp7J2n8)
18
18
 
19
19
  ## Installation
@@ -387,6 +387,16 @@ client.set_lock(
387
387
 
388
388
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
389
389
 
390
+ The default `bundle exec rake` task runs `lint` (standardrb auto-format), `spec`, and `e2e` (a hosted end-to-end smoke test against a real Qdrant deployment) in sequence. Because the E2E step needs real credentials, run it with your hosted endpoint and API key exported:
391
+
392
+ ```sh
393
+ export QDRANT_URL="https://<hosted-qdrant-endpoint>"
394
+ export QDRANT_API_KEY="<project-api-key>"
395
+ bundle exec rake
396
+ ```
397
+
398
+ The individual steps are also available as `bundle exec rake lint`, `bundle exec rake spec`, and `bundle exec rake e2e`. Run the hosted check against an isolated or disposable project, since it creates and deletes a temporary collection.
399
+
390
400
  To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
391
401
 
392
402
  ## Contributing
data/Rakefile CHANGED
@@ -1,8 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "bundler/gem_tasks"
4
+ require "rbconfig"
4
5
  require "rspec/core/rake_task"
5
6
 
6
7
  RSpec::Core::RakeTask.new(:spec)
7
8
 
8
- task default: :spec
9
+ desc "Run the standardrb linter (auto-fix)"
10
+ task :lint do
11
+ sh "bundle exec standardrb --fix"
12
+ end
13
+
14
+ desc "Run the hosted Qdrant API end-to-end smoke test"
15
+ task :e2e do
16
+ exec RbConfig.ruby, File.expand_path("script/e2e.rb", __dir__)
17
+ end
18
+
19
+ task default: %i[lint spec e2e]
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+
5
+ require_relative "request"
6
+ require_relative "response"
7
+
8
+ module Qdrant
9
+ class Client
10
+ class Connection
11
+ def initialize(url:, api_key:, raise_error:, logger:)
12
+ @uri = url
13
+ @api_key = api_key
14
+ @raise_error = raise_error
15
+ @logger = logger
16
+ end
17
+
18
+ def get(path, &block)
19
+ execute(Net::HTTP::Get, path, &block)
20
+ end
21
+
22
+ def post(path, &block)
23
+ execute(Net::HTTP::Post, path, &block)
24
+ end
25
+
26
+ def put(path, &block)
27
+ execute(Net::HTTP::Put, path, &block)
28
+ end
29
+
30
+ def patch(path, &block)
31
+ execute(Net::HTTP::Patch, path, &block)
32
+ end
33
+
34
+ def delete(path, &block)
35
+ execute(Net::HTTP::Delete, path, &block)
36
+ end
37
+
38
+ private
39
+
40
+ def execute(verb, path, &block)
41
+ response = RequestBuilder
42
+ .new(verb, @uri, path, @api_key, @logger)
43
+ .tap(&block)
44
+ .build
45
+ .perform(@raise_error)
46
+
47
+ ResponseBuilder.new(response).build
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "net/http"
5
+ require "uri"
6
+
7
+ module Qdrant
8
+ class Client
9
+ RequestData = Struct.new(:params, :body)
10
+
11
+ class RequestBuilder
12
+ def initialize(verb, base_url, path, api_key, logger)
13
+ raise ArgumentError, "unsupported HTTP verb" unless verb < Net::HTTPRequest
14
+
15
+ @verb = verb
16
+ @base_url = base_url
17
+ @path = path
18
+ @api_key = api_key
19
+ @logger = logger
20
+
21
+ @request = RequestData.new({}, nil)
22
+ end
23
+
24
+ def tap
25
+ yield @request if block_given?
26
+ self
27
+ end
28
+
29
+ def build
30
+ Request.new build_uri, @verb, @request.body, @api_key, @logger
31
+ end
32
+
33
+ private
34
+
35
+ def build_uri
36
+ path, query = @path.to_s.split("?", 2)
37
+
38
+ URI.join(@base_url, path).tap do |uri|
39
+ if (query_pairs = URI.decode_www_form(query.to_s) + @request.params.to_a).any?
40
+ uri.query = URI.encode_www_form(query_pairs)
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ class Request
47
+ def initialize(uri, verb, body, api_key, logger)
48
+ @logger = logger
49
+ @uri = uri
50
+ @verb = verb
51
+
52
+ @data = verb.new(uri.request_uri).tap do |request|
53
+ request["api-key"] = api_key if api_key
54
+
55
+ if body
56
+ request.body = JSON.generate(body)
57
+ request["Content-Type"] = request["Accept"] = "application/json"
58
+ end
59
+ end
60
+
61
+ logger.info("#{verb_name} #{uri}")
62
+ logger.info("Request headers: #{redacted_headers.inspect}")
63
+ logger.info("Request body: #{@data.body}") if @data.body
64
+ end
65
+
66
+ def perform(raise_error)
67
+ @logger.info("Performing Request: #{verb_name} #{@uri}")
68
+
69
+ response = Net::HTTP.new(@uri.host, @uri.port).tap do |h|
70
+ h.use_ssl = true if @uri.scheme == "https"
71
+ end.request(@data)
72
+
73
+ response.value if raise_error
74
+
75
+ @logger.info("Response status: #{response.code}")
76
+ response
77
+ rescue => e
78
+ @logger.error("#{verb_name} #{@uri} failed: #{e.class}: #{e.message}")
79
+ raise
80
+ end
81
+
82
+ private
83
+
84
+ def verb_name
85
+ @verb.name.split("::").last.upcase
86
+ end
87
+
88
+ def redacted_headers
89
+ @data.to_hash.tap do |headers|
90
+ headers["api-key"] = "[FILTERED]" if headers.key?("api-key")
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Qdrant
6
+ class Client
7
+ Response = Struct.new(:status, :headers, :body)
8
+
9
+ class ResponseBuilder
10
+ JSON_CONTENT_TYPE_REGEX = /\bjson\z/
11
+
12
+ def initialize(response)
13
+ @response = response
14
+ end
15
+
16
+ def build
17
+ Response.new(@response.code.to_i, @response.to_hash, parse_body)
18
+ end
19
+
20
+ private
21
+
22
+ def parse_body
23
+ body = @response.body
24
+ return body unless !body.nil? && !body.empty? && json_response?
25
+
26
+ JSON.parse(body)
27
+ rescue JSON::ParserError
28
+ # Fallback to raw body if JSON parsing fails unexpectedly
29
+ body
30
+ end
31
+
32
+ def json_response?
33
+ content_type = @response["Content-Type"]
34
+ return false if content_type.nil?
35
+
36
+ media_type = content_type.split(";").first.to_s.strip
37
+ media_type.match?(JSON_CONTENT_TYPE_REGEX)
38
+ end
39
+ end
40
+ end
41
+ end
data/lib/qdrant/client.rb CHANGED
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "faraday"
3
+ require "logger"
4
4
  require "forwardable"
5
5
 
6
+ require_relative "client/connection"
7
+
6
8
  module Qdrant
7
9
  class Client
8
10
  extend Forwardable
@@ -14,11 +16,11 @@ module Qdrant
14
16
  def initialize(
15
17
  url:,
16
18
  api_key: nil,
17
- adapter: Faraday.default_adapter,
18
19
  raise_error: false,
19
- logger: nil
20
+ logger: nil,
21
+ adapter: nil # Deprecated. Doesn't select the transport. Should be removed in subsequent releases
20
22
  )
21
- @url = url
23
+ @url = normalize_url(url)
22
24
  @api_key = api_key
23
25
  @adapter = adapter
24
26
  @raise_error = raise_error
@@ -26,16 +28,12 @@ module Qdrant
26
28
  end
27
29
 
28
30
  def connection
29
- @connection ||= Faraday.new(url: url) do |faraday|
30
- if api_key
31
- faraday.headers["api-key"] = api_key
32
- end
33
- faraday.request :json
34
- faraday.response :logger, @logger, {headers: true, bodies: true, errors: true}
35
- faraday.response :raise_error if raise_error
36
- faraday.response :json, content_type: /\bjson$/
37
- faraday.adapter adapter
38
- end
31
+ @connection ||= Connection.new(
32
+ url: url,
33
+ api_key: api_key,
34
+ raise_error: raise_error,
35
+ logger: logger
36
+ )
39
37
  end
40
38
 
41
39
  def aliases
@@ -61,5 +59,14 @@ module Qdrant
61
59
  def points
62
60
  @points ||= Qdrant::Points.new(client: self)
63
61
  end
62
+
63
+ private
64
+
65
+ def normalize_url(url)
66
+ raise ArgumentError, "url must be a String" unless url.is_a?(String)
67
+ return url if url.start_with?("http://", "https://")
68
+
69
+ "https://#{url}"
70
+ end
64
71
  end
65
72
  end
data/lib/qdrant/points.rb CHANGED
@@ -51,7 +51,6 @@ module Qdrant
51
51
  ordering: nil,
52
52
  filter: nil
53
53
  )
54
-
55
54
  raise ArgumentError, "Either points or filter should be provided" if points.nil? && filter.nil?
56
55
 
57
56
  response = client.connection.post("collections/#{collection_name}/#{PATH}/delete") do |req|
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Qdrant
4
- VERSION = "0.9.10"
4
+ VERSION = "0.10.0"
5
5
  end
data/script/e2e.rb ADDED
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "logger"
5
+ require "securerandom"
6
+ require "qdrant"
7
+
8
+ def assert!(condition, message)
9
+ raise "e2e assertion failed: #{message}" unless condition
10
+ end
11
+
12
+ def ok_body!(body, operation)
13
+ assert!(body.is_a?(Hash), "#{operation} returned #{body.class}, expected Hash")
14
+ assert!(body["status"] == "ok", "#{operation} returned status #{body["status"].inspect}")
15
+ body
16
+ end
17
+
18
+ url = ENV.fetch("QDRANT_URL", "").strip
19
+ api_key = ENV.fetch("QDRANT_API_KEY", "").strip
20
+
21
+ abort "QDRANT_URL must be set to an https:// hosted endpoint" if url.empty? || !url.start_with?("https://")
22
+ abort "QDRANT_API_KEY must be set" if api_key.empty?
23
+
24
+ logger = Logger.new($stderr)
25
+ logger.level = Logger::WARN
26
+
27
+ client = Qdrant::Client.new(
28
+ url: url,
29
+ api_key: api_key,
30
+ raise_error: true,
31
+ logger: logger
32
+ )
33
+
34
+ collection_name = "qdrant_ruby_e2e_#{Process.pid}_#{Time.now.utc.strftime("%Y%m%d%H%M%S")}_#{SecureRandom.hex(4)}"
35
+ collection_created = false
36
+ failure = nil
37
+
38
+ begin
39
+ body = ok_body!(client.collections.list, "collections.list")
40
+ assert!(body.dig("result", "collections").is_a?(Array), "collections.list result is not an Array")
41
+ puts "e2e: connection and authentication passed"
42
+
43
+ body = client.collections.create(
44
+ collection_name: collection_name,
45
+ vectors: {size: 3, distance: "Cosine"}
46
+ )
47
+ collection_created = true
48
+ ok_body!(body, "collections.create")
49
+ assert!(body["result"] == true, "collections.create did not return result=true")
50
+ puts "e2e: collection created (#{collection_name})"
51
+
52
+ body = ok_body!(client.collections.get(collection_name: collection_name), "collections.get")
53
+ status = body.dig("result", "status")
54
+ assert!(%w[green yellow].include?(status), "collection status was #{status.inspect}")
55
+
56
+ points = [
57
+ {id: 1, vector: [1.0, 0.0, 0.0], payload: {"source" => "hosted-e2e", "rank" => 1}},
58
+ {id: 2, vector: [0.0, 1.0, 0.0], payload: {"source" => "hosted-e2e", "rank" => 2}}
59
+ ]
60
+
61
+ body = ok_body!(
62
+ client.points.upsert(collection_name: collection_name, wait: true, points: points),
63
+ "points.upsert"
64
+ )
65
+ assert!(body.dig("result", "status") == "completed", "points.upsert did not return a completed status")
66
+
67
+ body = ok_body!(client.points.get(collection_name: collection_name, id: 1), "points.get")
68
+ assert!(body.dig("result", "id") == 1, "points.get returned the wrong point")
69
+
70
+ body = ok_body!(
71
+ client.points.get_all(
72
+ collection_name: collection_name,
73
+ ids: [1, 2],
74
+ with_payload: true,
75
+ with_vector: true
76
+ ),
77
+ "points.get_all"
78
+ )
79
+ results = body.fetch("result")
80
+ assert!(results.is_a?(Array) && results.length == 2, "points.get_all did not return two points")
81
+ assert!(results.map { |point| point["id"] }.sort == [1, 2], "points.get_all returned unexpected IDs")
82
+ assert!(results.find do |point|
83
+ point["id"] == 1
84
+ end.dig("payload", "source") == "hosted-e2e", "point payload was not persisted")
85
+ puts "e2e: point write and read round trip passed"
86
+
87
+ body = ok_body!(
88
+ client.points.search(
89
+ collection_name: collection_name,
90
+ vector: [1.0, 0.0, 0.0],
91
+ limit: 1,
92
+ with_payload: true,
93
+ with_vector: false
94
+ ),
95
+ "points.search"
96
+ )
97
+ hit = body.fetch("result").first
98
+ assert!(hit && hit["id"] == 1, "points.search did not return point 1 first")
99
+ assert!(hit["score"].to_f > 0.99, "points.search score was #{hit["score"].inspect}")
100
+
101
+ body = ok_body!(client.points.count(collection_name: collection_name, exact: true), "points.count")
102
+ assert!(body.dig("result", "count") == 2, "points.count did not return 2")
103
+ puts "e2e: search and count passed"
104
+
105
+ body = ok_body!(client.points.delete(collection_name: collection_name, points: [1, 2], wait: true), "points.delete")
106
+ assert!(body.dig("result", "status") == "completed", "points.delete did not return a completed status")
107
+ body = ok_body!(client.points.count(collection_name: collection_name, exact: true), "points.count after delete")
108
+ assert!(body.dig("result", "count") == 0, "points.count after delete did not return 0")
109
+ puts "e2e: point deletion passed"
110
+ rescue => e
111
+ failure = e
112
+ warn "e2e failed: #{e.class}: #{e.message}"
113
+ ensure
114
+ if collection_created
115
+ begin
116
+ body = ok_body!(client.collections.delete(collection_name: collection_name), "collections.delete cleanup")
117
+ assert!(body["result"] == true, "collections.delete cleanup did not return result=true")
118
+ puts "e2e: temporary collection deleted"
119
+ rescue => e
120
+ failure ||= e
121
+ warn "e2e cleanup failed: #{e.class}: #{e.message}"
122
+ end
123
+ end
124
+ end
125
+
126
+ if failure
127
+ exit 1
128
+ else
129
+ puts "e2e passed"
130
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qdrant-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.10
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrei Bondarev
@@ -10,25 +10,19 @@ cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
- name: faraday
13
+ name: logger
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 2.0.1
19
- - - "<"
20
- - !ruby/object:Gem::Version
21
- version: '3'
18
+ version: '0'
22
19
  type: :runtime
23
20
  prerelease: false
24
21
  version_requirements: !ruby/object:Gem::Requirement
25
22
  requirements:
26
23
  - - ">="
27
24
  - !ruby/object:Gem::Version
28
- version: 2.0.1
29
- - - "<"
30
- - !ruby/object:Gem::Version
31
- version: '3'
25
+ version: '0'
32
26
  - !ruby/object:Gem::Dependency
33
27
  name: pry-byebug
34
28
  requirement: !ruby/object:Gem::Requirement
@@ -63,6 +57,9 @@ files:
63
57
  - lib/qdrant/aliases.rb
64
58
  - lib/qdrant/base.rb
65
59
  - lib/qdrant/client.rb
60
+ - lib/qdrant/client/connection.rb
61
+ - lib/qdrant/client/request.rb
62
+ - lib/qdrant/client/response.rb
66
63
  - lib/qdrant/clusters.rb
67
64
  - lib/qdrant/collections.rb
68
65
  - lib/qdrant/error.rb
@@ -70,6 +67,7 @@ files:
70
67
  - lib/qdrant/service.rb
71
68
  - lib/qdrant/snapshots.rb
72
69
  - lib/qdrant/version.rb
70
+ - script/e2e.rb
73
71
  - sig/qdrant.rbs
74
72
  homepage: https://github.com/andreibondarev/qdrant-ruby
75
73
  licenses:
@@ -85,7 +83,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
85
83
  requirements:
86
84
  - - ">="
87
85
  - !ruby/object:Gem::Version
88
- version: 2.6.0
86
+ version: '3.3'
89
87
  required_rubygems_version: !ruby/object:Gem::Requirement
90
88
  requirements:
91
89
  - - ">="