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

FIX: default with_session client options #3

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

rreckonerr
Copy link

@rreckonerr rreckonerr commented Oct 2, 2024

The default HTTPClientOptions.new() parameter in with_session method raises an error. According to the README it should be possible to call with_session without passing any arguments.

@rreckonerr rreckonerr force-pushed the fix/default-with-session-client-options branch from ce8b579 to 6720a68 Compare October 2, 2024 11:53
JanEbbing
JanEbbing previously approved these changes Oct 2, 2024
Copy link
Member

@JanEbbing JanEbbing left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your work! This looks good to me overall, just 2 small nits.
I will also look to add a test case that uses with_session to make 2 requests in a VCR on top of your changes.

@@ -0,0 +1,63 @@
# frozen_string_literal: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit 1: please add this copyright header for new files

# Copyright 2024 DeepL SE (https://www.deepl.com)
# Use of this source code is governed by an MIT
# license that can be found in the LICENSE file.

@@ -0,0 +1,63 @@
# frozen_string_literal: true

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit 2: IMO this file should go under spec/http_client_options_spec.rb - integration_tests is reserved for files that make actual web requests to the API, and the spec/ folder in general emulates the structure of the source code in lib/.


require 'spec_helper'

describe DeepL::HTTPClientOptions do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding tests :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My pleasure!

The default `HTTPClientOptions.new()` parameter in `with_session` method raises an error. According to the [README](https://github.com/DeepLcom/deepl-rb/blob/1f63db3b704ec532c0b970a52fb8ec90c6986e84/README.md?plain=1#L344-L350) it should be possible to call `with_session` without passing any arguments.
@rreckonerr
Copy link
Author

@JanEbbing Thanks for quickly checking it out!

I have a question, maybe you have an idea of what's going on.
I used Concurrent::Promises before to make translation requests in parallel, but upgrading from 2.5.3 to 3.0.1 caused weird errors (like FrozenError can't modify frozen OpenSSL::SSL::SSLContext), so I refactored away to use the with_session. Do you think that it might indicate some thread-safety issues and whether there is a way to make the requests in parallel? I didn't manage to reproduce the issue in tests, unfortunately.

Below you can see the previous Concurrent::Promises usage

@@ -19,8 +19,8 @@ def translate_single(text, source_lang, target_lang, options = DEFAULT_OPTIONS)
   end
   
   def translate_multiple(text, source_lang, target_langs, options = DEFAULT_OPTIONS)
-    promises = target_langs.map do |target_lang|
-      Concurrent::Promises.future do
+    with_session(DeepL::HTTPClientOptions.new({}, nil)) do |_session|
+      target_langs.to_h do |target_lang|
         translation = translate(text, local_to_external(source_lang), local_to_external(target_lang), options.to_h.deep_dup)
         [external_to_local(target_lang), translation.text]
       rescue DeepL::Exceptions::Error => e
@@ -28,10 +28,6 @@ def translate_multiple(text, source_lang, target_langs, options = DEFAULT_OPTION
         [external_to_local(target_lang), nil]
       end
     end
-
-    results = Concurrent::Promises.zip(*promises).value!
-
-    results.to_h
   end

@JanEbbing
Copy link
Member

I'll look into this tomorrow - I did slightly change how the requests are made internally, but I dont think it should cause issues for this use case.

@JanEbbing
Copy link
Member

Hi, I cannot reproduce any issues with the following code:

require 'concurrent-ruby'
require 'deepl'


def translate_multiple(text, source_lang, target_langs)
  promises = target_langs.map do |target_lang|
    DeepL.with_session(DeepL::HTTPClientOptions.new({}, nil)) do |_session|
      Concurrent::Promises.future do
        DeepL.translate(text, source_lang, target_lang)
        rescue DeepL::Exceptions::Error => e
          puts e.message
      end
    end
  end
  return Concurrent::Promises.zip(*promises).value!
end

sample_text = 'I am an example sentence in english.' * 1000
target_langs = ['DE', 'ES', 'PT-BR', 'IT', 'ZH-HANS', 'KO']
res = translate_multiple(sample_text, 'EN', target_langs)
puts res

But I need to read a bit more to exclude any thread safety issues, as the with_session will use a Net::HTTP session now - to fix this, we might need to add a different HTTP client as a dependency.

@rreckonerr
Copy link
Author

This looks related getsentry/sentry-ruby#1696

For me the error pops up in production reliably, maybe it's related to yjit, which is enabled only in prod in my case, e.g.

RUN apt-get -qq install -y --no-install-recommends libjemalloc2

ENV LD_PRELOAD="libjemalloc.so.2"
ENV MALLOC_CONF="dirty_decay_ms:1000,narenas:2,background_thread:true"
ENV RUBY_YJIT_ENABLE="1"

@lasseebert
Copy link

I have the same FrozenError when running concurrent threads (with GoodJob in my case) that translate via DeepL. It seems to be because @http_client is reused between requests. Using with_session in each thread fixes it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants