Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improved message sending and draft create/update performance #470

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Changelog

### Unreleased
* Improved message sending and draft create/update performance
* Change default timeout to match API (90 seconds)

### 6.0.2 / 2024-02-27
Expand Down
27 changes: 23 additions & 4 deletions lib/nylas/resources/drafts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,20 @@ def find(identifier:, draft_id:)
# you can use {FileUtils::attach_file_request_builder} to build each object attach.
# @return [Array(Hash, String)] The created draft and API Request ID.
def create(identifier:, request_body:)
form_body, opened_files = FileUtils.build_form_request(request_body)
payload = request_body
opened_files = []

# Use form data only if the attachment size is greater than 3mb
attachments = request_body[:attachments] || request_body["attachments"] || []
attachment_size = attachments&.sum { |attachment| attachment[:size] || 0 } || 0

if attachment_size >= FileUtils::FORM_DATA_ATTACHMENT_SIZE
payload, opened_files = FileUtils.build_form_request(request_body)
end

response = post(
path: "#{api_uri}/v3/grants/#{identifier}/drafts",
request_body: form_body
request_body: payload
)

opened_files.each(&:close)
Expand All @@ -63,11 +73,20 @@ def create(identifier:, request_body:)
# you can use {FileUtils::attach_file_request_builder} to build each object attach.
# @return [Array(Hash, String)] The updated draft and API Request ID.
def update(identifier:, draft_id:, request_body:)
form_body, opened_files = FileUtils.build_form_request(request_body)
payload = request_body
opened_files = []

# Use form data only if the attachment size is greater than 3mb
attachments = request_body[:attachments] || request_body["attachments"] || []
attachment_size = attachments&.sum { |attachment| attachment[:size] || 0 } || 0

if attachment_size >= FileUtils::FORM_DATA_ATTACHMENT_SIZE
payload, opened_files = FileUtils.build_form_request(request_body)
end

response = put(
path: "#{api_uri}/v3/grants/#{identifier}/drafts/#{draft_id}",
request_body: form_body
request_body: payload
)

opened_files.each(&:close)
Expand Down
13 changes: 11 additions & 2 deletions lib/nylas/resources/messages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,20 @@ def destroy(identifier:, message_id:)
# you can use {FileUtils::attach_file_request_builder} to build each object attach.
# @return [Array(Hash, String)] The sent message and the API Request ID.
def send(identifier:, request_body:)
form_body, opened_files = FileUtils.build_form_request(request_body)
payload = request_body
opened_files = []

# Use form data only if the attachment size is greater than 3mb
attachments = request_body[:attachments] || request_body["attachments"] || []
attachment_size = attachments&.sum { |attachment| attachment[:size] || 0 } || 0

if attachment_size >= FileUtils::FORM_DATA_ATTACHMENT_SIZE
payload, opened_files = FileUtils.build_form_request(request_body)
end

response = post(
path: "#{api_uri}/v3/grants/#{identifier}/messages/send",
request_body: form_body
request_body: payload
)

opened_files.each(&:close)
Expand Down
3 changes: 3 additions & 0 deletions lib/nylas/utils/file_utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
module Nylas
# A collection of file-related utilities.
module FileUtils
# The maximum size of an attachment that can be sent using json
FORM_DATA_ATTACHMENT_SIZE = 3 * 1024 * 1024

# Build a form request for the API.
# @param request_body The values to create the message with.
# @return The form data to send to the API and the opened files.
Expand Down
59 changes: 56 additions & 3 deletions spec/nylas/resources/drafts_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,33 @@
expect(draft_response).to eq(response)
end

it "calls the post method with the correct parameters and attachments" do
it "calls the post method with the correct parameters for small attachments" do
identifier = "abc-123-grant-id"
mock_file = instance_double("file")
request_body = {
subject: "Hello from Nylas!",
to: [{ name: "Jon Snow", email: "[email protected]" }],
cc: [{ name: "Arya Stark", email: "[email protected]" }],
body: "This is the body of my draft message.",
attachments: [{
filename: "file.txt",
content_type: "text/plain",
size: 100,
content: mock_file
}]
}
path = "#{api_uri}/v3/grants/#{identifier}/drafts"

allow(drafts).to receive(:post)
.with(path: path, request_body: request_body)
.and_return(response)

draft_response = drafts.create(identifier: identifier, request_body: request_body)

expect(draft_response).to eq(response)
end

it "calls the post method with the correct parameters for large attachments" do
identifier = "abc-123-grant-id"
mock_file = instance_double("file")
request_body = {
Expand All @@ -109,7 +135,7 @@
attachment = {
filename: "file.txt",
content_type: "text/plain",
size: 100,
size: 3 * 1024 * 1024,
content: mock_file
}
expected_compiled_request = {
Expand Down Expand Up @@ -154,6 +180,33 @@
end

it "calls the put method with the correct parameters and attachments" do
identifier = "abc-123-grant-id"
draft_id = "5d3qmne77v32r8l4phyuksl2x"
mock_file = instance_double("file")
request_body = {
subject: "Hello from Nylas!",
to: [{ name: "Jon Snow", email: "[email protected]" }],
cc: [{ name: "Arya Stark", email: "[email protected]" }],
body: "This is the body of my draft message.",
attachments: [{
filename: "file.txt",
content_type: "text/plain",
size: 100,
content: mock_file
}]
}
path = "#{api_uri}/v3/grants/#{identifier}/drafts/#{draft_id}"
allow(drafts).to receive(:put)
.with(path: path, request_body: request_body)
.and_return(response)

draft_response = drafts.update(identifier: identifier, draft_id: draft_id,
request_body: request_body)

expect(draft_response).to eq(response)
end

it "calls the put method with the correct parameters for large attachments" do
identifier = "abc-123-grant-id"
draft_id = "5d3qmne77v32r8l4phyuksl2x"
mock_file = instance_double("file")
Expand All @@ -166,7 +219,7 @@
attachment = {
filename: "file.txt",
content_type: "text/plain",
size: 100,
size: 3 * 1024 * 1024,
content: mock_file
}
expected_compiled_request = {
Expand Down
28 changes: 27 additions & 1 deletion spec/nylas/resources/messages_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,32 @@
end

it "calls the post method with the correct parameters and attachments" do
identifier = "abc-123-grant-id"
mock_file = instance_double("file")
request_body = {
subject: "Hello from Nylas!",
to: [{ name: "Jon Snow", email: "[email protected]" }],
cc: [{ name: "Arya Stark", email: "[email protected]" }],
body: "This is the body of my message message.",
attachments: [{
filename: "file.txt",
content_type: "text/plain",
size: 100,
content: mock_file
}]
}
path = "#{api_uri}/v3/grants/#{identifier}/messages/send"

allow(messages).to receive(:post)
.with(path: path, request_body: request_body)
.and_return(response)

message_response = messages.send(identifier: identifier, request_body: request_body)

expect(message_response).to eq(response)
end

it "calls the post method with the correct parameters and large attachments" do
identifier = "abc-123-grant-id"
mock_file = instance_double("file")
request_body = {
Expand All @@ -146,7 +172,7 @@
attachment = {
filename: "file.txt",
content_type: "text/plain",
size: 100,
size: 3 * 1024 * 1024,
content: mock_file
}
expected_compiled_request = {
Expand Down
Loading