dse-driver 1.0.1 → 2.0.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,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