Skip to content

Commit

Permalink
Improved message sending and draft create/update performance (#470)
Browse files Browse the repository at this point in the history
This PR improves message send/draft create/update performance by always defaulting to application/json instead of multipart. Multipart will only be used for when a request contains a total attachments size of 3mb or higher.
  • Loading branch information
mrashed-dev authored Mar 5, 2024
1 parent fe73d9c commit 0639d65
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 10 deletions.
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

0 comments on commit 0639d65

Please sign in to comment.