dse-driver 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- M2YwYzhhNTk0YzgxZTFkMzg2NGQyZWI0MDkyYmIxZTg4OWQ3OGZhZA==
4
+ OWQ3OTgyN2JlZWI5MWZkZmU3YWU5ZmY5MmI1ZWJjMjlkY2RmN2FiMw==
5
5
  data.tar.gz: !binary |-
6
- YTQ2NWY1NDJjMTRiY2U5OGVhNWVjNTYxYTc3YjAxOTM3NmEyMDA3ZQ==
6
+ YWUzMjJkMWIwZjI5N2RlOGJiYjI5M2QzOTEwMTJlNmIyM2M5YjcxYg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NGEyZTY1NmMxMThiZTY0YjJlZmQxMzE2MmUxY2ZkODUwNGUyOWVmZjZkNTIw
10
- NjQ3OWI3NDJiMjJhMTM3ODkxOGEzMGZhNmRjYjdhMzI5YjMzNWY0ZjZiZTFj
11
- ZjcyNzlkMTU0YjIyNDRmODQ2Yjk3ODU3ODc3Yzk1NDdkY2ZmNzk=
9
+ ODViODg2OTU5ZDQ2ZmYzODJhYzZhNWM2ODNmNTllNTk3YmM3ODJhYWIzZmRj
10
+ YTE0ZjRhYzRlNTc4ZTBiNmQ2ZjRkYzVlYmNhMTA4YTgyOGMzNDhmYTdmZWFh
11
+ ODNjYTY4ZmQwYTM2NGVhMzY2ODY3MjU1MmNhZDcxOWRlNDg1ZjA=
12
12
  data.tar.gz: !binary |-
13
- OGU0MTJkOTNmMzQ0YzgzNGNlNWMwMjQ1MDllNzhkNTcxYWQ5NTFhZTc4NTc2
14
- NTc4NTljNDczNzQyOThlNDk5NTc3NjcwNzAwYmI0MjUyMjc1YTkyNjFmM2M5
15
- YTVmZTZjZGMzMGU5ZTY2NzcwNzVmY2JhYWQ0ZGRhZTQ0YzRmODM=
13
+ MDM2ZTQyNTkzODg2MDZhZTE5NmJjNTFlMzg0M2E1YmFmMThhYTBhMjI2Y2Iy
14
+ MDlmNWU5YTE0OGNkNzZhZmEwYjJmZTc4NDRjMDM5Yjk1OTMwOTRiM2E0YzBj
15
+ NGViN2FjZjYwY2NhYzNmOGEzM2ZhYTcwNmQ4MTc2ODMyMjk3OTg=
data/README.md CHANGED
@@ -2,15 +2,14 @@
2
2
 
3
3
  *NOTE: The DataStax Enterprise Ruby Driver can be used solely with DataStax Enterprise. Please consult [the license](http://www.datastax.com/terms/datastax-dse-driver-license-terms).*
4
4
 
5
- This driver is built on top of the [DataStax Ruby driver for Apache Cassandra](http://docs.datastax.com/en/latest-ruby-driver/ruby-driver/whatsNew.html)
5
+ This driver is built on top of the [DataStax Ruby driver for Apache Cassandra](http://dsdocs30)
6
6
  and enhanced for the adaptive data management and mixed workload capabilities
7
7
  provided by DSE. Therefore a lot of the underlying concepts are the same.
8
8
 
9
9
  ## Documentation
10
- Driver documentation can be found [here](http://docs.datastax.com/en/latest-dse-ruby-driver/ruby-driver/whatsNew.html).
10
+ Driver documentation can be found [here](http://docs.datastax.com/en/developer/ruby-driver-dse).
11
11
 
12
- In particular, you'll find our [Features](http://docs.datastax.com/en/latest-dse-ruby-driver/supplemental/features) and
13
- [API](http://docs.datastax.com/en/latest-dse-ruby-driver/supplemental/api) sections very enlightening.
12
+ In particular, you'll find our [Features](features) and [API](api) sections very enlightening.
14
13
 
15
14
  ## Feedback Requested
16
15
  *Help us focus our efforts!* [Provide your input](http://goo.gl/forms/pCs8PTpHLf) on the Ruby Driver
@@ -51,6 +50,72 @@ session = cluster.connect
51
50
  rs = session.execute('select * from system.local')
52
51
  ```
53
52
 
53
+
54
+ ## Breaking changes in 2.0
55
+ This release adds support for [graph execution profiles](features/graph#execution-profiles). As a result, the cluster-level `graph_options` object has
56
+ been removed. That object is effectively stored in the `:default_graph` execution profile. However, since execution
57
+ profiles are read-only, graph options in profiles cannot be manipulated. Instead, either specify new graph
58
+ options at query execution time, or use separate execution profiles for your different scenarios.
59
+
60
+ Furthermore, the `Dse::Graph::Options` class is no longer in the public api. Instead of constructing a
61
+ `Dse::Graph::Options` object and passing it to `Session.execute_graph*`, you must now pass the primitive graph options
62
+ or specify the name of an execution profile that encapsulates the desired graph options. Similarly, when creating a
63
+ `Dse::Graph::Statement`, you must specify primitive graph options instead of a `Dse::Graph::Options` object.
64
+
65
+ Since execution profiles are immutable, you must set expert options at construction time with the `expert_options`
66
+ hash. See the [documentation](features/graph#expert-options) for more details.
67
+
68
+ Another behavior change is that in v1.x, graph query timeout defaulted to unlimited. This caused queries to fall back to
69
+ server timeouts. The default was set this way to accommodate multi-day analytics queries and multi-second OLTP queries
70
+ without requiring intervention / special handling from the user. The introduction of execution profiles into the driver
71
+ enables the user to more easily run different types of queries:
72
+
73
+ ```ruby
74
+ # Use the default graph profile with its OLTP-motivated timeout (30 seconds)
75
+ rs = session.execute_graph('g.V()')
76
+ # Use the default graph analytics profile for an OLAP query (timeout 7 days)
77
+ rs = session.execute_graph('g.V()', execution_profile: :default_graph_analytics
78
+ # Use the default system query profile for graph system queries (timeout 3 minutes)
79
+ rs = session.execute_graph("system.graph('mygraph').exists()",
80
+ execution_profile: :default_graph_system)
81
+ ```
82
+ Thus, no query runs with unlimited timeout by default as of this version of the driver.
83
+
84
+ Finally, in v1.x, graph query timeout was specified via the `:timeout` option in calls to `Session.execute_graph*` or
85
+ packaged up in a graph options object. Since the graph execution profile now assumes the role of graph options, use
86
+ the `:timeout` attribute in the graph execution profile to specify graph timeout. In particular, to set the default
87
+ graph timeout for graph queries, you must define your own `:default_graph` execution profile that will take precedence
88
+ over one that would normally be generated by the driver:
89
+
90
+ ```ruby
91
+ cluster = Dse.cluster(execution_profiles: {
92
+ default_graph: Dse::Graph::ExecutionProfile.new(timeout: 17, graph_name: 'mygraph')
93
+ })
94
+ ```
95
+
96
+ In the example above, the default graph timeout is set to 17 seconds. Note that you are not permitted to mix
97
+ primitive options (that are now available in execution profiles) with an execution_profiles hash when creating
98
+ the cluster object:
99
+
100
+ ```ruby
101
+ # Illegal!
102
+ cluster = Dse.cluster(execution_profiles: {
103
+ default_graph: Dse::Graph::ExecutionProfile.new(timeout: 17, graph_name: 'mygraph')
104
+ }, timeout: 7)
105
+
106
+ ```
107
+
108
+ Thus, in order to specify that non-graph queries should execute with a timeout of 7 seconds by default, you must
109
+ override the Cassandra default execution profile, named `:default`:
110
+
111
+ ```ruby
112
+ # Legal.
113
+ cluster = Dse.cluster(execution_profiles: {
114
+ default_graph: Dse::Graph::ExecutionProfile.new(timeout: 17, graph_name: 'mygraph'),
115
+ default: Cassandra::Execution::Profile.new(timeout: 7)
116
+ })
117
+ ```
118
+
54
119
  ## Determining driver versions
55
120
  Within a script or irb, you can determine the exact versions of the dse and core drivers by accessing the VERSION
56
121
  constant of the appropriate module:
@@ -69,4 +134,4 @@ previous versions of DSE.
69
134
  ## License
70
135
  Copyright (C) 2016 DataStax Inc.
71
136
 
72
- The full license terms are available at http://www.datastax.com/terms/datastax-dse-driver-license-terms
137
+ The full license terms are available at http://www.datastax.com/terms/datastax-dse-driver-license-terms
data/lib/dse.rb CHANGED
@@ -22,8 +22,6 @@ module Dse
22
22
  # The API is identical, except that it returns a {Dse::Session Dse::Session} (see below). It takes all of the same
23
23
  # options as Cassandra.cluster and the following extra options.
24
24
  #
25
- # @option options [Dse::Graph::Options] :graph_options options for the DSE graph statement handler. Takes
26
- # priority over other `:graph_*` options specified below.
27
25
  # @option options [String] :graph_name name of graph to use in graph statements
28
26
  # @option options [String] :graph_source graph traversal source
29
27
  # @option options [String] :graph_language language used in graph queries
@@ -54,16 +52,20 @@ module Dse
54
52
  # @return [Cassandra::Future<Dse::Cluster>] a future resolving to the
55
53
  # cluster instance.
56
54
  def self.cluster_async(options = {})
57
- graph_options = if !options[:graph_options].nil?
58
- Cassandra::Util.assert_instance_of(Dse::Graph::Options, options[:graph_options])
59
- options[:graph_options]
60
- else
61
- Dse::Graph::Options.new(options)
62
- end
55
+ if options.key?(:execution_profiles)
56
+ [:graph_name, :graph_source, :graph_language, :graph_read_consistency, :graph_write_consistency].each do |opt|
57
+ raise ::ArgumentError, "#{opt} is not allowed when execution profiles are used" if options.key?(opt)
58
+ end
59
+ end
60
+
63
61
  username = options[:username]
64
62
  password = options[:password]
65
63
  options[:custom_types] ||= []
66
64
  options[:custom_types] << Dse::Geometry::Point << Dse::Geometry::LineString << Dse::Geometry::Polygon
65
+
66
+ # validate_and_massage will return a new options hash, with non-C* options removed. Hold onto the original hash
67
+ # for attributes we still need later.
68
+ full_options = options
67
69
  options, hosts = Cassandra.validate_and_massage_options(options)
68
70
 
69
71
  # Use the DSE plain text authenticator if we have a username and password. The above validation already
@@ -75,18 +77,45 @@ module Dse
75
77
  else
76
78
  options[:cluster_klass] = Dse::Cluster
77
79
  driver = ::Cassandra::Driver.new(options)
80
+ system_defaults = ::Cassandra::Driver.new
81
+ profile_manager = driver.profile_manager
82
+ unless profile_manager.profiles.key?(:default_graph)
83
+ # full_options has the graph options. But we don't want to use other attributes like load_balancing_policy, etc.
84
+ # in defining our default graph profile. So make a new hash that explicitly sets core profile attributes to
85
+ # system defaults.
86
+ graph_profile = Dse::Graph::ExecutionProfile.new(
87
+ full_options.merge(timeout: 30,
88
+ load_balancing_policy: system_defaults.load_balancing_policy,
89
+ retry_policy: system_defaults.retry_policy,
90
+ consistency: system_defaults.consistency
91
+ ))
92
+ profile_manager.add_profile(:default_graph, graph_profile)
93
+ end
94
+ unless profile_manager.profiles.key?(:default_graph_system)
95
+ graph_profile = Dse::Graph::ExecutionProfile.new(graph_read_consistency: full_options[:graph_read_consistency],
96
+ graph_write_consistency: full_options[:graph_write_consistency],
97
+ timeout: 180)
98
+ profile_manager.add_profile(:default_graph_system, graph_profile)
99
+ end
100
+ unless profile_manager.profiles.key?(:default_graph_analytics)
101
+ # Wrap the system default load-balancing policy that we'd otherwise run, with a host-targeting policy, for the
102
+ # analytics profile.
78
103
 
79
- # Wrap the load-balancing policy that we'd otherwise run with, with a host-targeting policy.
80
- # We do this before driver.connect because driver.connect saves off the policy in the cluster
81
- # registry and does a few other things.
82
-
83
- lbp = driver.load_balancing_policy
84
- driver.load_balancing_policy = Dse::LoadBalancing::Policies::HostTargeting.new(lbp)
85
- future = driver.connect(hosts)
86
- future.then do |cluster|
87
- cluster.graph_options.merge!(graph_options)
88
- cluster
104
+ # We do this before driver.connect because driver.connect saves off the policy in the cluster
105
+ # registry and does a few other things.
106
+ graph_profile = Dse::Graph::ExecutionProfile.new(
107
+ graph_source: 'a',
108
+ graph_name: full_options[:graph_name],
109
+ graph_read_consistency: full_options[:graph_read_consistency],
110
+ graph_write_consistency: full_options[:graph_write_consistency],
111
+ load_balancing_policy: Dse::LoadBalancing::Policies::HostTargeting.new(
112
+ system_defaults.load_balancing_policy
113
+ ),
114
+ timeout: (3600 * 24 * 7)
115
+ )
116
+ profile_manager.add_profile(:default_graph_analytics, graph_profile)
89
117
  end
118
+ driver.connect(hosts)
90
119
  end
91
120
  end
92
121
 
data/lib/dse/cluster.rb CHANGED
@@ -11,9 +11,6 @@ module Dse
11
11
  # Cluster represents a DSE cluster. It serves as a {Dse::Session session factory} and a collection of metadata.
12
12
  # It wraps a {http://dsdocs30/api/cassandra/cluster Cassandra::Cluster} and exposes all of its functionality.
13
13
  class Cluster
14
- # @return [Dse::Graph::Options] default graph options used by queries on this cluster.
15
- attr_reader :graph_options
16
-
17
14
  # @private
18
15
  def initialize(logger,
19
16
  io_reactor,
@@ -24,9 +21,8 @@ module Dse
24
21
  cluster_metadata,
25
22
  execution_options,
26
23
  connection_options,
27
- load_balancing_policy,
24
+ profile_manager,
28
25
  reconnection_policy,
29
- retry_policy,
30
26
  address_resolution_policy,
31
27
  connector,
32
28
  futures_factory,
@@ -40,21 +36,21 @@ module Dse
40
36
  cluster_metadata,
41
37
  execution_options,
42
38
  connection_options,
43
- load_balancing_policy,
39
+ profile_manager,
44
40
  reconnection_policy,
45
- retry_policy,
46
41
  address_resolution_policy,
47
42
  connector,
48
43
  futures_factory,
49
44
  timestamp_generator)
50
- @graph_options = Dse::Graph::Options.new
51
-
52
45
  # We need the futures factory ourselves for async error reporting and potentially for our
53
46
  # own async processing independent of the C* driver.
54
47
  @futures = futures_factory
48
+
49
+ # Similarly for profile-manager
50
+ @profile_manager = profile_manager
55
51
  end
56
52
 
57
- # Delegates to {http://docs.datastax.com/en/developer/ruby-driver/3.0/supplemental/api/cassandra/cluster/?local=true&nav=toc#connect_async-instance_method
53
+ # Delegates to {http://dsdocs30/api/cassandra/cluster/?local=true&nav=toc#connect_async-instance_method
58
54
  # Cassandra::Cluster#connect_async}
59
55
  # to connect asynchronously to a cluster, but returns a future that will resolve to a DSE session rather than
60
56
  # Cassandra session.
@@ -66,7 +62,7 @@ module Dse
66
62
  future = @delegate_cluster.connect_async(keyspace)
67
63
  # We want to actually return a DSE session upon successful connection.
68
64
  future.then do |cassandra_session|
69
- Dse::Session.new(cassandra_session, @graph_options, @futures)
65
+ Dse::Session.new(cassandra_session, @profile_manager, @futures)
70
66
  end
71
67
  end
72
68
 
@@ -79,6 +75,12 @@ module Dse
79
75
  connect_async(keyspace).get
80
76
  end
81
77
 
78
+ # @private
79
+ def inspect
80
+ "#<#{self.class.name}:0x#{object_id.to_s(16)} " \
81
+ "@delegate_cluster=#{@delegate_cluster.inspect}>"
82
+ end
83
+
82
84
  #### The following methods handle arbitrary delegation to the underlying cluster object. ####
83
85
  protected
84
86
 
data/lib/dse/graph.rb CHANGED
@@ -8,6 +8,7 @@
8
8
  #++
9
9
 
10
10
  require 'dse/graph/edge'
11
+ require 'dse/graph/execution_profile'
11
12
  require 'dse/graph/options'
12
13
  require 'dse/graph/path'
13
14
  require 'dse/graph/result'
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+
3
+ #--
4
+ # Copyright (C) 2016 DataStax Inc.
5
+ #
6
+ # This software can be used solely with DataStax Enterprise. Please consult the license at
7
+ # http://www.datastax.com/terms/datastax-dse-driver-license-terms
8
+ #++
9
+
10
+ module Dse
11
+ module Graph
12
+ # @!parse
13
+ # # Execution profile class that adds graph option support
14
+ # class ExecutionProfile < ::Cassandra::Execution::Profile
15
+ # # @return [String] name of the targeted graph; required unless the statement is a system query.
16
+ # attr_accessor :graph_name
17
+ # # @return [String] graph traversal source (default "g")
18
+ # attr_accessor :graph_source
19
+ # # @return [String] language used in the graph statement (default "gremlin-groovy")
20
+ # attr_accessor :graph_language
21
+ # # @return [Cassandra::CONSISTENCIES] read consistency level for graph statement.
22
+ # # Overrides the standard statement consistency level. Defaults to ONE in the server,
23
+ # # but the default may be configured differently.
24
+ # attr_accessor :graph_read_consistency
25
+ # # @return [Cassandra::CONSISTENCIES] write consistency level for graph statement.
26
+ # # Overrides the standard statement consistency level. Defaults to QUORUM in the server,
27
+ # # but the default may be configured differently.
28
+ # attr_accessor :graph_write_consistency
29
+ # end
30
+
31
+
32
+ class ExecutionProfile < ::Cassandra::Execution::Profile
33
+ extend Forwardable
34
+
35
+ # @private
36
+ attr_reader :graph_options
37
+
38
+ def_delegators :@graph_options, :graph_name, :graph_source, :graph_language, :graph_read_consistency,
39
+ :graph_write_consistency
40
+
41
+ # Creates a {ExecutionProfile} instance, which extends
42
+ # {http://dsdocs/api/cassandra/execution/profile Cassandra::Execution::Profile}.
43
+ # It takes all of the same options as the Cassandra::Execution::Profile constructor and
44
+ # the following extra options.
45
+ #
46
+ # @option options [String] :graph_name name of graph to use in graph statements
47
+ # @option options [String] :graph_source graph traversal source
48
+ # @option options [String] :graph_language language used in graph queries
49
+ # @option options [Cassandra::CONSISTENCIES] :graph_read_consistency read consistency level for graph statements.
50
+ # Overrides the standard statement consistency level
51
+ # @option options [Cassandra::CONSISTENCIES] :graph_write_consistency write consistency level for
52
+ # graph statements. Overrides the standard statement consistency level
53
+ def initialize(options = {})
54
+ options[:timeout] = 30 unless options[:timeout]
55
+ super(options)
56
+ @graph_options = Dse::Graph::Options.new(options)
57
+ end
58
+
59
+ # @private
60
+ def eql?(other)
61
+ other.is_a?(ExecutionProfile) && \
62
+ super(other) && \
63
+ @graph_options == other.graph_options
64
+ end
65
+ alias == eql?
66
+
67
+ # @private
68
+ def hash
69
+ @hash ||= begin
70
+ h = super.hash
71
+ h = 31 * h + @graph_options.hash
72
+ h
73
+ end
74
+ end
75
+
76
+ # @private
77
+ def inspect
78
+ "#<Dse::Graph::ExecutionProfile:0x#{object_id.to_s(16)} " \
79
+ "super=#{super.inspect}, " \
80
+ "@graph_name=#{@graph_options.graph_name.inspect}, " \
81
+ "@graph_source=#{@graph_options.graph_source.inspect}, " \
82
+ "@graph_language=#{@graph_options.graph_language.inspect}, " \
83
+ "@graph_read_consistency=#{@graph_options.graph_read_consistency.inspect}, " \
84
+ "@graph_write_consistency=#{@graph_options.graph_write_consistency.inspect}>"
85
+ end
86
+ end
87
+ end
88
+ end
@@ -9,29 +9,8 @@
9
9
 
10
10
  module Dse
11
11
  module Graph
12
- # @!parse
13
- # class Options
14
- # # @return [String] name of the targeted graph; required unless the statement is a system query.
15
- # attr_accessor :graph_name
16
- # # @return [String] graph traversal source (default "g")
17
- # attr_accessor :graph_source
18
- # # @return [String] language used in the graph statement (default "gremlin-groovy")
19
- # attr_accessor :graph_language
20
- # # @return [Cassandra::CONSISTENCIES] read consistency level for graph statement.
21
- # # Overrides the standard statement consistency level. Defaults to ONE in the server,
22
- # # but the default may be configured differently.
23
- # attr_accessor :graph_read_consistency
24
- # # @return [Cassandra::CONSISTENCIES] write consistency level for graph statement.
25
- # # Overrides the standard statement consistency level. Defaults to QUORUM in the server,
26
- # # but the default may be configured differently.
27
- # attr_accessor :graph_write_consistency
28
- # end
29
-
30
- # Options for DSE Graph queries
12
+ # @private Options for DSE Graph queries
31
13
  class Options
32
- # @return [Numeric] the timeout for graph requests
33
- attr_reader :timeout
34
-
35
14
  # @private
36
15
  DEFAULT_GRAPH_OPTIONS = {
37
16
  'graph-source' => 'g',
@@ -59,64 +38,40 @@ module Dse
59
38
  set(k, v) if OPTION_NAMES.include?(k)
60
39
  end
61
40
 
62
- set_timeout(options[:timeout])
41
+ # Set expert options, if available.
42
+ if options.key?(:expert_options)
43
+ options[:expert_options].each do |k, v|
44
+ set(k, v)
45
+ end
46
+ end
63
47
  end
64
48
 
65
49
  OPTION_NAMES.each do |attr|
66
50
  define_method(attr.to_s) do
67
51
  @real_options[stringify(attr)]
68
52
  end
69
-
70
- define_method("#{attr}=") do |value|
71
- @real_options[stringify(attr)] = value
72
- end
73
53
  end
74
54
 
75
55
  # @private
76
- def timeout=(val)
77
- set_timeout(val)
78
- val
56
+ def eql?(other)
57
+ other.is_a?(Options) && \
58
+ @real_options == other.instance_variable_get(:@real_options)
79
59
  end
60
+ alias == eql?
80
61
 
81
62
  # @private
82
- # rubocop:disable Style/AccessorMethodName
83
- def set_timeout(new_timeout)
84
- @timeout = new_timeout
85
- if @timeout
86
- @real_options['request-timeout'] = [@timeout * 1000].pack('Q>')
87
- else
88
- @real_options.delete('request-timeout')
89
- end
90
- nil
91
- end
92
-
93
- # Set an option in this {Options} object. This is primarily used to set "expert" options that
94
- # are not part of the public api and thus may change over time.
95
- # @param key [String, Symbol] option to set.
96
- # @param value [String] value to set for the option.
97
- # @return [Options] self, thus allowing method chaining.
98
- def set(key, value)
99
- string_key = stringify(key)
100
- if string_key == 'timeout'
101
- set_timeout(value)
102
- elsif value
103
- @real_options[stringify(key)] = value
104
- end
105
- self
63
+ def hash
64
+ @hash ||= 31 * 17 + @real_options.hash
106
65
  end
107
66
 
108
- # Delete an option from this {Options} object.
109
- # @param key [String, Symbol] option to delete.
110
- # @return nil
111
- def delete(key)
112
- string_key = stringify(key)
113
- if string_key == 'timeout'
114
- @timeout = nil
115
- @real_options.delete('request-timeout')
116
- else
117
- @real_options.delete(string_key)
118
- end
119
- nil
67
+ # @private
68
+ def inspect
69
+ "#<Dse::Graph::Options:0x#{object_id.to_s(16)} " \
70
+ "@graph_name=#{@real_options['graph-name'].inspect}, " \
71
+ "@graph_source=#{@real_options['graph-source'].inspect}, " \
72
+ "@graph_language=#{@real_options['graph-language'].inspect}, " \
73
+ "@graph_read_consistency=#{@real_options['graph-read-consistency'].inspect}, " \
74
+ "@graph_write_consistency=#{@real_options['graph-write-consistency'].inspect}>"
120
75
  end
121
76
 
122
77
  # Merge another {Options} object with this one to produce a new merged {Options} object.
@@ -131,63 +86,38 @@ module Dse
131
86
  result = Options.new
132
87
  result.instance_variable_set(:@real_options,
133
88
  @real_options.merge(other.instance_variable_get(:@real_options)))
134
- other_timeout = other.instance_variable_get(:@timeout)
135
- result.instance_variable_set(:@timeout,
136
- other_timeout ? other_timeout : @timeout)
137
89
  result
138
90
  end
139
91
 
140
- # Clear the options within this {Options} object.
141
- def clear
142
- @real_options.clear
143
- @timeout = nil
144
- end
145
-
146
92
  # @private
147
93
  def stringify(attr)
148
94
  attr.to_s.tr('_', '-')
149
95
  end
150
96
 
151
- # @private
152
- def merge!(other)
153
- result = merge(other)
154
- @real_options = result.instance_variable_get(:@real_options)
155
- @timeout = result.instance_variable_get(:@timeout)
156
- self
157
- end
158
-
159
97
  # @return whether or not this options object is configured for the analytics graph source.
160
98
  def analytics?
161
99
  @real_options['graph-source'] == 'a'
162
100
  end
163
101
 
164
102
  # @private
165
- def as_payload
103
+ def as_payload(timeout = nil)
166
104
  # Merge in real options with defaults to get a final payload
167
- DEFAULT_GRAPH_OPTIONS.merge(@real_options)
168
- end
169
-
170
- # @private
171
- def eql?(other)
172
- other.is_a?(Options) && \
173
- @real_options == other.instance_variable_get(:@real_options)
105
+ result = DEFAULT_GRAPH_OPTIONS.merge(@real_options)
106
+ result['request-timeout'] = [timeout * 1000].pack('Q>') unless timeout.nil?
107
+ result
174
108
  end
175
- alias == eql?
176
109
 
177
- # @private
178
- def hash
179
- @hash ||= 31 * 17 + @real_options.hash
180
- end
110
+ private
181
111
 
182
- # @private
183
- def inspect
184
- "#<Dse::Graph::Options:0x#{object_id.to_s(16)} " \
185
- "@graph_name=#{@real_options['graph-name'].inspect}, " \
186
- "@graph_source=#{@real_options['graph-source'].inspect}, " \
187
- "@graph_language=#{@real_options['graph-language'].inspect}, " \
188
- "@graph_read_consistency=#{@real_options['graph-read-consistency'].inspect}, " \
189
- "@graph_write_consistency=#{@real_options['graph-write-consistency'].inspect}, " \
190
- "@timeout=#{@timeout.inspect}>"
112
+ # Set an option in this {Options} object. This is primarily used to set "expert" options that
113
+ # are not part of the public api and thus may change over time.
114
+ # @param key [String, Symbol] option to set.
115
+ # @param value [String] value to set for the option.
116
+ # @return [Options] self, thus allowing method chaining.
117
+ def set(key, value)
118
+ raise "can't modify frozen Dse::Graph::Options" if frozen?
119
+ @real_options[stringify(key)] = value if value
120
+ self
191
121
  end
192
122
  end
193
123
  end
@@ -13,19 +13,40 @@ module Dse
13
13
  # re-issuing the same statement multiple times the same way.
14
14
  class Statement
15
15
  include Cassandra::Statement
16
+ extend Forwardable
17
+
18
+ # @!method graph_name
19
+ # @return [String] name of the targeted graph; required unless the statement is a system query.
20
+ #
21
+ # @!method graph_source
22
+ # @return [String] graph traversal source (default "g")
23
+ #
24
+ # @!method graph_language
25
+ # @return [String] language used in the graph statement (default "gremlin-groovy")
26
+ #
27
+ # @!method graph_read_consistency
28
+ # @return [Cassandra::CONSISTENCIES] read consistency level for graph statement.
29
+ # Overrides the standard statement consistency level. Defaults to ONE in the server,
30
+ # but the default may be configured differently.
31
+ # @!method graph_write_consistency
32
+ # @return [Cassandra::CONSISTENCIES] write consistency level for graph statement.
33
+ # Overrides the standard statement consistency level. Defaults to QUORUM in the server,
34
+ # but the default may be configured differently.
35
+ def_delegators :@options, :graph_name, :graph_source, :graph_language, :graph_read_consistency,
36
+ :graph_write_consistency
16
37
 
17
38
  # @return [String] graph statement string
18
39
  attr_reader :statement
19
40
  # @return [Hash<String, String>] parameters to the statement
20
41
  attr_reader :parameters
21
- # @return [Options] graph options
42
+ # @private
22
43
  attr_reader :options
23
44
  # @private
24
45
  attr_reader :simple_statement
25
46
 
26
47
  # @param statement [String] graph statement
27
48
  # @param parameters [Hash<String, String>] (nil) parameters to the statement
28
- # @param options [Hash, Options] (nil) graph options
49
+ # @param options [Hash] (nil) graph options
29
50
  # @param idempotent [Boolean] (false) whether or not the statement is idempotent
30
51
  def initialize(statement, parameters = nil, options = nil, idempotent = false)
31
52
  # Save off statement and idempotent; easy stuff.
@@ -46,22 +67,10 @@ module Dse
46
67
  parameters = [tweaked_params.to_json]
47
68
  end
48
69
 
49
- # Graph options may be tricky. A few cases:
50
- # 1. options is nil; then @options should be nil.
51
- # 2. options is a Hash with a graph_options key; then @options is the referenced Options object.
52
- # We must validate that the referenced object *is* an Options.
53
- # 3. options is an Options object; then just assign to @options.
54
-
55
- unless options.nil?
56
- Cassandra::Util.assert_instance_of_one_of([Dse::Graph::Options, ::Hash], options)
57
- @options = if options.is_a?(Options)
58
- options
59
- elsif !options[:graph_options].nil?
60
- Cassandra::Util.assert_instance_of(Dse::Graph::Options, options[:graph_options])
61
- options[:graph_options]
62
- else
63
- Dse::Graph::Options.new(options)
64
- end
70
+ # Create a Graph::Options object only if we have non-nil options.
71
+ unless options.nil? || options.empty?
72
+ Cassandra::Util.assert_instance_of(::Hash, options)
73
+ @options = Dse::Graph::Options.new(options)
65
74
  end
66
75
 
67
76
  @simple_statement = Cassandra::Statements::Simple.new(@statement,
data/lib/dse/session.rb CHANGED
@@ -16,9 +16,9 @@ module Dse
16
16
  # @see http://dsdocs30/api/cassandra/session Cassandra::Session
17
17
  class Session
18
18
  # @private
19
- def initialize(cassandra_session, graph_options, futures_factory)
19
+ def initialize(cassandra_session, profile_manager, futures_factory)
20
20
  @cassandra_session = cassandra_session
21
- @graph_options = graph_options
21
+ @profile_manager = profile_manager
22
22
  @futures = futures_factory
23
23
  end
24
24
 
@@ -28,8 +28,6 @@ module Dse
28
28
  # {Cassandra::Session#execute_async} are valid here. However, there are some extras, noted below.
29
29
  # @option options [Hash] :arguments Parameters for the graph statement.
30
30
  # NOTE: Unlike {#execute} and {#execute_async}, this must be a hash of &lt;parameter-name,value>.
31
- # @option options [Dse::Graph::Options] :graph_options options for the DSE graph statement handler. Takes
32
- # priority over other `:graph_*` options specified below.
33
31
  # @option options [String] :graph_name name of graph to use in graph statements
34
32
  # @option options [String] :graph_source graph traversal source
35
33
  # @option options [String] :graph_language language used in graph queries
@@ -37,6 +35,8 @@ module Dse
37
35
  # Overrides the standard statement consistency level
38
36
  # @option options [Cassandra::CONSISTENCIES] :graph_write_consistency write consistency level for graph statements.
39
37
  # Overrides the standard statement consistency level
38
+ # @option options [String, Symbol] :execution_profile (:default_graph) name of {Dse::Graph::ExecutionProfile}
39
+ # from which to obtain certain query options.
40
40
  # @return [Cassandra::Future<Cassandra::Result>]
41
41
  # @see http://dsdocs30/api/cassandra/session#execute_async-instance_method
42
42
  # Cassandra::Session::execute_async for all of the core options.
@@ -45,15 +45,28 @@ module Dse
45
45
  # about to do some destructive mutations.
46
46
 
47
47
  options = options.dup
48
+
48
49
  Cassandra::Util.assert_instance_of_one_of([String, Dse::Graph::Statement], graph_statement)
50
+ arguments = nil
51
+ if options
52
+ Cassandra::Util.assert_instance_of(::Hash, options)
53
+ arguments = options.delete(:arguments)
54
+ end
49
55
 
50
56
  if graph_statement.is_a?(String)
51
- graph_statement = Dse::Graph::Statement.new(graph_statement, options[:arguments], options, options[:idempotent])
57
+ graph_statement = Dse::Graph::Statement.new(graph_statement, arguments, options, options[:idempotent])
52
58
  end
53
59
 
54
- graph_options = @graph_options.merge(graph_statement.options)
55
- options[:payload] = graph_options.as_payload
56
- options[:timeout] = graph_options.timeout
60
+ options[:execution_profile] ||= :default_graph
61
+ profile = @profile_manager.profiles[options[:execution_profile]]
62
+ Cassandra::Util.assert(!profile.nil?, "Profile '#{options[:execution_profile]}' does not exist")
63
+ Cassandra::Util.assert_instance_of(Dse::Graph::ExecutionProfile, profile)
64
+
65
+ graph_options = profile.graph_options.merge(graph_statement.options)
66
+
67
+ # The custom payload should have a 'request-timeout' that is the value of the :timeout option, if specified.
68
+ # Otherwise, fall back to the timeout in the execution profile.
69
+ options[:payload] = graph_options.as_payload(options[:timeout] || profile.timeout)
57
70
 
58
71
  if graph_options.analytics?
59
72
  @cassandra_session.execute_async('CALL DseClientTool.getAnalyticsGraphServer()').then do |rows|
data/lib/dse/version.rb CHANGED
@@ -8,5 +8,5 @@
8
8
  #++
9
9
 
10
10
  module Dse
11
- VERSION = '1.0.1'.freeze
11
+ VERSION = '2.0.0'.freeze
12
12
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dse-driver
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandeep Tamhankar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-02 00:00:00.000000000 Z
11
+ date: 2016-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cassandra-driver
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 3.0.3
19
+ version: 3.1.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 3.0.3
26
+ version: 3.1.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -77,6 +77,7 @@ files:
77
77
  - lib/dse/graph.rb
78
78
  - lib/dse/graph/duration.rb
79
79
  - lib/dse/graph/edge.rb
80
+ - lib/dse/graph/execution_profile.rb
80
81
  - lib/dse/graph/options.rb
81
82
  - lib/dse/graph/path.rb
82
83
  - lib/dse/graph/result.rb