Class: Graphd::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/graphd/transaction.rb

Overview

A transaction to perform queries and mutations

A transaction bounds a sequence of queries and mutations that are committed by Dgraph as a single unit: that is, on commit, either all the changes are accepted by Dgraph or none are.

Instance Method Summary collapse

Constructor Details

#initialize(client, read_only: false, best_effort: false) ⇒ Transaction

Create a new transaction

Parameters:

  • client (Graphd::Client)

    The client for which the transaction needs to be created

  • read_only (true, false) (defaults to: false)

    whether the transaction should be read only Read-only transactions are ideal for transactions which only involve queries. Mutations and commits are not allowed.

  • best_effort (true, false) (defaults to: false)

    Enable best-effort queries Best-effort queries are faster than normal queries because they bypass the normal consensus protocol. For this same reason, best-effort queries cannot guarantee to return the latest data. Best-effort queries are only supported by read-only transactions.



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/graphd/transaction.rb', line 24

def initialize(client, read_only: false, best_effort: false)
  if !read_only && best_effort
    raise TransactionError, 'Best effort transactions are only compatible with read-only transactions'
  end

  @client = client
  @client_stub = @client.client
  @transaction_context = ::Api::TxnContext.new
  @finished = false
  @mutated = false
  @read_only = read_only
  @best_effort = best_effort
end

Instance Method Details

#commitObject



156
157
158
159
160
161
162
163
164
# File 'lib/graphd/transaction.rb', line 156

def commit
  return unless common_commit

  begin
    @client_stub.commit_or_abort(transaction_context: @transaction_context)
  rescue StandardError => e
    common_except_commit(e)
  end
end

#create_mutation(mutation: nil, set_obj: nil, del_obj: nil, set_nquads: nil, del_nquads: nil, cond: nil) ⇒ Api::Mutation

Create or modify an instance of Api::Mutation with the provided configuration

Parameters:

  • mutation (Api::Mutation) (defaults to: nil)

    (optional) A mutation to be modified

  • set_obj (Hash) (defaults to: nil)

    (optional) A Hash that represent a value to be set This value will be set the value of set_json of Api::Mutation

  • del_obj (Hash) (defaults to: nil)

    (optional) A Hash that represents a value to be deleted This value will be set the value of delete_json of Api::Mutation

  • set_nquads (String) (defaults to: nil)

    (optional) An N-Quad representing the value to be set for Api::Mutation

  • del_nquads (String) (defaults to: nil)

    (optional) An N-Quad representing the value to be deleted for Api::Mutation

Returns:



61
62
63
64
65
66
67
68
69
70
71
# File 'lib/graphd/transaction.rb', line 61

def create_mutation(mutation: nil, set_obj: nil, del_obj: nil, set_nquads: nil, del_nquads: nil, cond: nil)
  mutation ||= ::Api::Mutation.new

  mutation.set_json = set_obj.to_json if set_obj
  mutation.delete_json = del_obj.to_json if del_obj
  mutation.set_nquads = set_nquads if set_nquads
  mutation.del_nquads = del_nquads if del_nquads
  mutation.cond = cond if cond

  mutation
end

#create_request(query: nil, variables: nil, mutations: nil, commit_now: nil) ⇒ Api::Request

Create an instance of Api::Request

Parameters:

  • query (String) (defaults to: nil)

    (optional) A GraphQL query as a string

  • query (Hash) (defaults to: nil)

    (optional) A Hash of variables used in the provided query The keys can be symbols or strings but not numbers. The values must be strings

  • mutations (Array<Api::Mutation>) (defaults to: nil)

    A list of mutations

  • commit_now (true, false) (defaults to: nil)

    Indicate that the mutation must be immediately committed. This can be used when the mutation needs to be committed, without querying anything further.

Returns:



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/graphd/transaction.rb', line 85

def create_request(query: nil, variables: nil, mutations: nil, commit_now: nil)
  request = ::Api::Request.new(
    start_ts: @transaction_context.start_ts,
    commit_now: commit_now,
    read_only: true,
    best_effort: true
  )
  variables&.each do |key, value|
    unless key.is_a?(Symbol) || key.is_a?(String)
      raise TransactionError, 'Keys in variable map must be symbols or strings'
    end

    raise TransactionError, 'Values in variable map must be strings' unless value.is_a?(String)

    request.vars[key] = value
  end

  request.query = query if query
  request.mutations += mutations if mutations

  request
end

#discardObject



134
135
136
137
138
# File 'lib/graphd/transaction.rb', line 134

def discard
  return unless common_discard

  @client_stub.commit_or_abort(transaction_context: @transaction_context)
end

#do_request(request) ⇒ Object

Raises:



108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/graphd/transaction.rb', line 108

def do_request(request)
  raise TransactionError, 'Transaction has already been committed or discarded' if @finished

  if request.mutations.length.positive?
    raise TransactionError, 'Readonly transaction cannot run mutations' if @read_only

    @mutated = true
  end

  query_error = nil

  begin
    @response = @client_stub.query(request)
  rescue StandardError => e
    query_error = e
  end

  discard if query_error

  @finished = true if request.commit_now

  merge_context(@response.txn)

  @response
end

#merge_context(src = nil) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/graphd/transaction.rb', line 140

def merge_context(src = nil)
  # This condition will be true only if the server doesn't return a
  # txn context after a query or mutation.
  return unless src

  if @transaction_context.start_ts.zero?
    @transaction_context.start_ts = src.start_ts
  elsif @transaction_context.start_ts != src.start_ts
    # This condition should never be true.
    raise TransactionError, 'StartTs mismatch'
  end

  @transaction_context.keys += src.keys
  @transaction_context.preds += src.preds
end

#mutate(mutation: nil, set_obj: nil, del_obj: nil, commit_now: nil) ⇒ Object



38
39
40
41
42
43
# File 'lib/graphd/transaction.rb', line 38

def mutate(mutation: nil, set_obj: nil, del_obj: nil, commit_now: nil)
  request_mutation = create_mutation(mutation: mutation, set_obj: set_obj, del_obj: del_obj)
  commit_now ||= request_mutation.commit_now
  request = create_request(mutations: [request_mutation], commit_now: commit_now)
  do_request(request)
end

#query(query, variables: nil) ⇒ Object



45
46
47
48
# File 'lib/graphd/transaction.rb', line 45

def query(query, variables: nil)
  request = create_request(query: query, variables: variables)
  do_request(request)
end