lucid-shopify 0.57.0 → 0.60.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 +4 -4
- data/README.md +12 -7
- data/lib/lucid/shopify/bulk_request.rb +97 -80
- data/lib/lucid/shopify/client.rb +8 -2
- data/lib/lucid/shopify/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2000b0881f8f32a1ae28c1e81f75c4e10c99fb386e090087c930835453a7c20
|
4
|
+
data.tar.gz: 871ddf85d10f96e5f03c253436d4fb49f76da54ed0e1bca68428fa2ae4cd095e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 17cbb58d6af88ebe841ff7ad8d2217512a7a11c78f40763a9061ef85e4e132d0334cce964235eed844d7d231a2657107ac3a493a091b6b2aba360d8f4042f925
|
7
|
+
data.tar.gz: bfebbb6f59bb8592827a6b3264c00bef9d3839e9236628d4e8eb91da30af9cc032e15500d389f366d4c8c7b967b8bbe75612d28d3de8658e3124fc13d1495661
|
data/README.md
CHANGED
@@ -101,9 +101,7 @@ Since API version 2019-10, Shopify has offered an API for bulk requests (using
|
|
101
101
|
the GraphQL API). The gem wraps this API, by writing the result to a temporary
|
102
102
|
file and yielding each line of the result to limit memory usage.
|
103
103
|
|
104
|
-
client.bulk(credentials)
|
105
|
-
db.transaction { y.() }
|
106
|
-
end.(<<~QUERY) do |product|
|
104
|
+
client.bulk(credentials, <<~QUERY) do |products|
|
107
105
|
{
|
108
106
|
products {
|
109
107
|
edges {
|
@@ -115,12 +113,19 @@ file and yielding each line of the result to limit memory usage.
|
|
115
113
|
}
|
116
114
|
}
|
117
115
|
QUERY
|
118
|
-
db
|
119
|
-
|
120
|
-
|
121
|
-
|
116
|
+
db.transaction do
|
117
|
+
products.each do |product|
|
118
|
+
db[:products].insert(
|
119
|
+
id: product['id'],
|
120
|
+
handle: product['handle'],
|
121
|
+
)
|
122
|
+
end
|
123
|
+
end
|
122
124
|
end
|
123
125
|
|
126
|
+
Bulk requests are limited to one per shop at any one time. Calling a new bulk
|
127
|
+
request via lucid-shopify will cancel any request in progress for the shop.
|
128
|
+
|
124
129
|
|
125
130
|
### Pagination
|
126
131
|
|
@@ -19,59 +19,35 @@ module Lucid
|
|
19
19
|
param :client
|
20
20
|
# @return [Credentials]
|
21
21
|
param :credentials
|
22
|
+
# @return [String]
|
23
|
+
param :id
|
22
24
|
end
|
23
25
|
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
26
|
+
# Wait for the operation to complete, then download the JSONL result
|
27
|
+
# data which is yielded as an {Enumerator} to the block. The data is
|
28
|
+
# streamed and parsed line by line to limit memory usage.
|
27
29
|
#
|
28
|
-
# @return [self]
|
29
|
-
#
|
30
|
-
# @example
|
31
|
-
# operation.around do |&y|
|
32
|
-
# puts 'Before iteration'
|
33
|
-
# y.()
|
34
|
-
# ensure
|
35
|
-
# puts 'After iteration'
|
36
|
-
# end
|
37
|
-
def around(&block)
|
38
|
-
@around = block
|
39
|
-
|
40
|
-
self
|
41
|
-
end
|
42
|
-
|
43
|
-
# Call the block set by {#around}.
|
44
|
-
#
|
45
|
-
# @yield inside the wrapper block
|
46
|
-
private def call_around(&block)
|
47
|
-
@around.respond_to?(:call) ? @around.(&block) : block.()
|
48
|
-
end
|
49
|
-
|
50
|
-
# @param query [String] the GraphQL query
|
51
30
|
# @param delay [Integer] delay between polling requests in seconds
|
52
31
|
# @param http [HTTP::Client]
|
53
32
|
#
|
54
|
-
# @yield [Hash] each parsed line of JSONL
|
55
|
-
def call(
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
QUERY
|
73
|
-
|
74
|
-
url = poll(id, delay: delay)
|
33
|
+
# @yield [Enumerator<Hash>] yields each parsed line of JSONL
|
34
|
+
def call(delay: 1, http: Container[:http], &block)
|
35
|
+
url = loop do
|
36
|
+
status, url = poll
|
37
|
+
|
38
|
+
case status
|
39
|
+
when 'CANCELED'
|
40
|
+
raise CanceledOperationError
|
41
|
+
when 'EXPIRED'
|
42
|
+
raise ExpiredOperationError
|
43
|
+
when 'FAILED'
|
44
|
+
raise FailedOperationError
|
45
|
+
when 'COMPLETED'
|
46
|
+
break url
|
47
|
+
else
|
48
|
+
sleep(delay)
|
49
|
+
end
|
50
|
+
end
|
75
51
|
|
76
52
|
return if url.nil?
|
77
53
|
|
@@ -84,22 +60,38 @@ module Lucid
|
|
84
60
|
file.write(chunk)
|
85
61
|
end
|
86
62
|
file.rewind
|
87
|
-
|
88
|
-
file.each_line
|
89
|
-
|
90
|
-
end
|
91
|
-
end
|
63
|
+
block.(Enumerator.new do |y|
|
64
|
+
file.each_line { |line| y << JSON.parse(line) }
|
65
|
+
end)
|
92
66
|
ensure
|
93
67
|
file.close
|
94
68
|
file.unlink
|
95
69
|
end
|
96
70
|
end
|
97
71
|
|
98
|
-
#
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
72
|
+
# Cancel the bulk operation.
|
73
|
+
def cancel
|
74
|
+
client.post_graphql(credentials, <<~QUERY)
|
75
|
+
mutation {
|
76
|
+
bulkOperationCancel(id: "#{id}") {
|
77
|
+
userErrors {
|
78
|
+
field
|
79
|
+
message
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
QUERY
|
84
|
+
|
85
|
+
loop do
|
86
|
+
status, _ = poll
|
87
|
+
|
88
|
+
break unless status == 'CANCELING'
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# @return [Array(String, String | nil)] the operation status and the
|
93
|
+
# download URL, or nil if the result data is empty
|
94
|
+
private def poll
|
103
95
|
op = client.post_graphql(credentials, <<~QUERY)['data']['currentBulkOperation']
|
104
96
|
{
|
105
97
|
currentBulkOperation {
|
@@ -112,32 +104,23 @@ module Lucid
|
|
112
104
|
|
113
105
|
raise ObsoleteOperationError if op['id'] != id
|
114
106
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
raise ExpiredOperationError
|
120
|
-
when 'FAILED'
|
121
|
-
raise FailedOperationError
|
122
|
-
when 'COMPLETED'
|
123
|
-
op['url']
|
124
|
-
else
|
125
|
-
sleep(delay)
|
126
|
-
|
127
|
-
poll(id, delay: delay)
|
128
|
-
end
|
107
|
+
[
|
108
|
+
op['status'],
|
109
|
+
op['url'],
|
110
|
+
]
|
129
111
|
end
|
130
112
|
end
|
131
113
|
|
114
|
+
# Create and start a new bulk operation via the GraphQL API.
|
115
|
+
#
|
132
116
|
# @param client [Client]
|
133
117
|
# @param credentials [Credentials]
|
118
|
+
# @param query [String] the GraphQL query
|
134
119
|
#
|
135
120
|
# @return [Operation]
|
136
121
|
#
|
137
122
|
# @example
|
138
|
-
# bulk_request.(client, credentials).
|
139
|
-
# db.transaction { y.() }
|
140
|
-
# end.(<<~QUERY) do |product|
|
123
|
+
# bulk_request.(client, credentials, <<~QUERY).() do |products|
|
141
124
|
# {
|
142
125
|
# products {
|
143
126
|
# edges {
|
@@ -149,15 +132,49 @@ module Lucid
|
|
149
132
|
# }
|
150
133
|
# }
|
151
134
|
# QUERY
|
152
|
-
# db
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
135
|
+
# db.transaction do
|
136
|
+
# products.each do |product|
|
137
|
+
# db[:products].insert(
|
138
|
+
# id: product['id'],
|
139
|
+
# handle: product['handle'],
|
140
|
+
# )
|
141
|
+
# end
|
142
|
+
# end
|
156
143
|
# end
|
157
|
-
def call(client, credentials)
|
144
|
+
def call(client, credentials, query)
|
158
145
|
Shopify.assert_api_version!('2019-10')
|
159
146
|
|
160
|
-
|
147
|
+
op = client.post_graphql(credentials, <<~QUERY)['data']['currentBulkOperation']
|
148
|
+
{
|
149
|
+
currentBulkOperation {
|
150
|
+
id
|
151
|
+
status
|
152
|
+
url
|
153
|
+
}
|
154
|
+
}
|
155
|
+
QUERY
|
156
|
+
|
157
|
+
Operation.new(client, credentials, op['id']).cancel if op && op['status'] == 'RUNNING'
|
158
|
+
|
159
|
+
id = client.post_graphql(credentials, <<~QUERY)['data']['bulkOperationRunQuery']['bulkOperation']['id']
|
160
|
+
mutation {
|
161
|
+
bulkOperationRunQuery(
|
162
|
+
query: """
|
163
|
+
#{query}
|
164
|
+
"""
|
165
|
+
) {
|
166
|
+
bulkOperation {
|
167
|
+
id
|
168
|
+
}
|
169
|
+
userErrors {
|
170
|
+
field
|
171
|
+
message
|
172
|
+
}
|
173
|
+
}
|
174
|
+
}
|
175
|
+
QUERY
|
176
|
+
|
177
|
+
Operation.new(client, credentials, id)
|
161
178
|
end
|
162
179
|
end
|
163
180
|
end
|
data/lib/lucid/shopify/client.rb
CHANGED
@@ -62,9 +62,15 @@ module Lucid
|
|
62
62
|
AuthenticatedClient.new(self, credentials)
|
63
63
|
end
|
64
64
|
|
65
|
+
# If called with a block, calls {BulkRequest::Operation#call} immediately,
|
66
|
+
# else, returns the {BulkRequest::Operation}.
|
67
|
+
#
|
65
68
|
# @see BulkRequest#call
|
66
|
-
|
67
|
-
|
69
|
+
# @see BulkRequest::Operation#call
|
70
|
+
def bulk(*args, &block)
|
71
|
+
op = @bulk_request.(self, *args)
|
72
|
+
|
73
|
+
block ? op.(&block) : op
|
68
74
|
end
|
69
75
|
|
70
76
|
# @see DeleteRequest#initialize
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lucid-shopify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.60.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kelsey Judson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dotenv
|