From dad265185b1c79c51acb3f7b10550be193108c68 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 25 Mar 2024 14:35:58 +1300 Subject: [PATCH 01/14] Graceful close on shared bound endpoints. (#80) --- lib/async/io/shared_endpoint.rb | 13 +++------- spec/async/io/shared_endpoint_spec.rb | 37 ++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/lib/async/io/shared_endpoint.rb b/lib/async/io/shared_endpoint.rb index 75018eb..c5dd76b 100644 --- a/lib/async/io/shared_endpoint.rb +++ b/lib/async/io/shared_endpoint.rb @@ -77,16 +77,9 @@ def bind task = Async::Task.current @wrappers.each do |server| - server = server.dup - task.async do |task| task.annotate "binding to #{server.inspect}" - - begin - yield server, task - ensure - server.close - end + yield server, task end end end @@ -109,9 +102,9 @@ def connect end end - def accept(backlog = nil, &block) + def accept(backlog = nil, **options, &block) bind do |server| - server.accept_each(&block) + server.accept_each(**options, &block) end end diff --git a/spec/async/io/shared_endpoint_spec.rb b/spec/async/io/shared_endpoint_spec.rb index c9d4316..1827c0f 100644 --- a/spec/async/io/shared_endpoint_spec.rb +++ b/spec/async/io/shared_endpoint_spec.rb @@ -10,7 +10,7 @@ include_context Async::RSpec::Reactor describe '#bound' do - let(:endpoint) {Async::IO::Endpoint.udp("localhost", 5123, timeout: 10)} + let(:endpoint) {Async::IO::Endpoint.tcp("localhost", 5123, timeout: 10)} it "can bind to shared endpoint" do bound_endpoint = described_class.bound(endpoint) @@ -33,6 +33,41 @@ bound_endpoint.close end + + it "can close a bound endpoint to terminate accept loop" do + bound_endpoint = described_class.bound(endpoint) + expect(bound_endpoint.wrappers).to_not be_empty + + server_task = Async do + bound_endpoint.accept do |io| + io.close + end + end + + connect = proc do + endpoint.connect do |io| + io.write "Hello World" + io.close + end + end + + connect.call + + wrapper = bound_endpoint.wrappers.first + expect(wrapper).to be_a Async::IO::Socket + + bound_endpoint.close + expect(wrapper).to be_closed + + expect do + begin + # Either ECONNRESET or ECONNREFUSED can be raised here. + connect.call + rescue Errno::ECONNRESET + raise Errno::ECONNREFUSED + end + end.to raise_error(Errno::ECONNREFUSED) + end end describe '#connected' do From 085b506b9bc5b4669f1d65b6fe1b972f09442932 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Mon, 25 Mar 2024 14:37:05 +1300 Subject: [PATCH 02/14] Bump minor version. --- lib/async/io/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/async/io/version.rb b/lib/async/io/version.rb index 9a9b416..b6ecc54 100644 --- a/lib/async/io/version.rb +++ b/lib/async/io/version.rb @@ -5,6 +5,6 @@ module Async module IO - VERSION = "1.41.0" + VERSION = "1.42.0" end end From 97a940281ca37f7446e16ab4d4b7e6f710dee1c7 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 17 Apr 2024 00:16:17 +1200 Subject: [PATCH 03/14] Modernize gem. (#81) --- .editorconfig | 4 + .github/workflows/coverage.yaml | 10 +- .github/workflows/documentation.yaml | 11 +-- .github/workflows/test-external.yaml | 3 +- .github/workflows/test.yaml | 5 +- async-io.gemspec | 14 ++- conduct.md | 133 -------------------------- examples/ssl/client.rb | 4 + examples/ssl/server.rb | 4 + gems.rb | 7 ++ gems/async-head.rb | 1 + gems/async-v1.rb | 1 + lib/async/io.rb | 2 +- lib/async/io/endpoint.rb | 2 +- lib/async/io/generic.rb | 1 + lib/async/io/shared_endpoint.rb | 2 +- lib/async/io/ssl_endpoint.rb | 2 +- lib/async/io/stream.rb | 1 + lib/async/io/unix_endpoint.rb | 1 + lib/async/io/version.rb | 2 +- license.md | 9 +- readme.md | 8 ++ spec/async/io/generic_spec.rb | 1 + spec/async/io/shared_endpoint_spec.rb | 2 +- spec/async/io/stream_spec.rb | 2 + spec/async/io/unix_endpoint_spec.rb | 1 + 26 files changed, 67 insertions(+), 166 deletions(-) delete mode 100644 conduct.md diff --git a/.editorconfig b/.editorconfig index 538ba2b..a6e7d26 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,3 +3,7 @@ root = true [*] indent_style = tab indent_size = 2 + +[*.{yml,yaml}] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index 81f3c65..68adbf2 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -21,10 +21,10 @@ jobs: - macos ruby: - - "3.2" + - "3.3" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} @@ -34,7 +34,7 @@ jobs: timeout-minutes: 5 run: bundle exec bake test - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 with: name: coverage-${{matrix.os}}-${{matrix.ruby}} path: .covered.db @@ -44,10 +44,10 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: - ruby-version: "3.2" + ruby-version: "3.3" bundler-cache: true - uses: actions/download-artifact@v3 diff --git a/.github/workflows/documentation.yaml b/.github/workflows/documentation.yaml index 3d483fc..8dc5227 100644 --- a/.github/workflows/documentation.yaml +++ b/.github/workflows/documentation.yaml @@ -5,9 +5,6 @@ on: branches: - main - # Allows you to run this workflow manually from the Actions tab: - workflow_dispatch: - # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages: permissions: contents: read @@ -28,11 +25,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: - ruby-version: "3.2" + ruby-version: "3.3" bundler-cache: true - name: Installing packages @@ -43,7 +40,7 @@ jobs: run: bundle exec bake utopia:project:static --force no - name: Upload documentation artifact - uses: actions/upload-pages-artifact@v1 + uses: actions/upload-pages-artifact@v2 with: path: docs @@ -58,4 +55,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 + uses: actions/deploy-pages@v3 diff --git a/.github/workflows/test-external.yaml b/.github/workflows/test-external.yaml index 214149c..7516fa7 100644 --- a/.github/workflows/test-external.yaml +++ b/.github/workflows/test-external.yaml @@ -24,9 +24,10 @@ jobs: - "3.0" - "3.1" - "3.2" + - "3.3" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 5c765b6..0769a98 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -21,10 +21,9 @@ jobs: - macos ruby: - - "2.7" - - "3.0" - "3.1" - "3.2" + - "3.3" experimental: [false] @@ -40,7 +39,7 @@ jobs: experimental: true steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} diff --git a/async-io.gemspec b/async-io.gemspec index 85ce5d1..8f417e0 100644 --- a/async-io.gemspec +++ b/async-io.gemspec @@ -7,7 +7,7 @@ Gem::Specification.new do |spec| spec.version = Async::IO::VERSION spec.summary = "Provides support for asynchonous TCP, UDP, UNIX and SSL sockets." - spec.authors = ["Samuel Williams", "Olle Jonsson", "Benoit Daloze", "Thibaut Girka", "Janko Marohnić", "Aurora Nockert", "Bruno Sutic", "Cyril Roelandt", "Hal Brodigan", "Jiang Jinyang"] + spec.authors = ["Samuel Williams", "Olle Jonsson", "Benoit Daloze", "Thibaut Girka", "Hal Brodigan", "Janko Marohnić", "Aurora Nockert", "Bruno Sutic", "Cyril Roelandt", "Hasan Kumar", "Jiang Jinyang", "Maruth Goyal", "Patrik Wenger"] spec.license = "MIT" spec.cert_chain = ['release.cert'] @@ -15,16 +15,14 @@ Gem::Specification.new do |spec| spec.homepage = "https://github.com/socketry/async-io" + spec.metadata = { + "documentation_uri" => "https://socketry.github.io/async-io/", + "source_code_uri" => "https://github.com/socketry/async-io.git", + } + spec.files = Dir.glob(['{lib}/**/*', '*.md'], File::FNM_DOTMATCH, base: __dir__) spec.required_ruby_version = ">= 2.5" spec.add_dependency "async" - - spec.add_development_dependency "async-container", "~> 0.15" - spec.add_development_dependency "async-rspec", "~> 1.10" - spec.add_development_dependency "bake" - spec.add_development_dependency "covered" - spec.add_development_dependency "rack-test" - spec.add_development_dependency "rspec", "~> 3.6" end diff --git a/conduct.md b/conduct.md deleted file mode 100644 index 45d257b..0000000 --- a/conduct.md +++ /dev/null @@ -1,133 +0,0 @@ - -# Contributor Covenant Code of Conduct - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, caste, color, religion, or sexual -identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -* Demonstrating empathy and kindness toward other people -* Being respectful of differing opinions, viewpoints, and experiences -* Giving and gracefully accepting constructive feedback -* Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -* Focusing on what is best not just for us as individuals, but for the overall - community - -Examples of unacceptable behavior include: - -* The use of sexualized language or imagery, and sexual attention or advances of - any kind -* Trolling, insulting or derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or email address, - without their explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official e-mail address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -[INSERT CONTACT METHOD]. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series of -actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or permanent -ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the -community. - -## Attribution - -This Code of Conduct is adapted from the [Contributor Covenant][homepage], -version 2.1, available at -[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1]. - -Community Impact Guidelines were inspired by -[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. - -For answers to common questions about this code of conduct, see the FAQ at -[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at -[https://www.contributor-covenant.org/translations][translations]. - -[homepage]: https://www.contributor-covenant.org -[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html -[Mozilla CoC]: https://github.com/mozilla/diversity -[FAQ]: https://www.contributor-covenant.org/faq -[translations]: https://www.contributor-covenant.org/translations diff --git a/examples/ssl/client.rb b/examples/ssl/client.rb index 06cf5eb..5a8e2c6 100644 --- a/examples/ssl/client.rb +++ b/examples/ssl/client.rb @@ -1,4 +1,8 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + +# Released under the MIT License. +# Copyright, 2023, by Hal Brodigan. require 'async' require 'async/io' diff --git a/examples/ssl/server.rb b/examples/ssl/server.rb index 8233ece..792f512 100644 --- a/examples/ssl/server.rb +++ b/examples/ssl/server.rb @@ -1,4 +1,8 @@ #!/usr/bin/env ruby +# frozen_string_literal: true + +# Released under the MIT License. +# Copyright, 2023, by Hal Brodigan. require 'async' require 'async/io' diff --git a/gems.rb b/gems.rb index 6b136d4..80d6801 100644 --- a/gems.rb +++ b/gems.rb @@ -17,10 +17,17 @@ end group :test do + gem "rspec", "~> 3.6" + gem "async-rspec", "~> 1.10" + gem "covered" + + gem "bake" gem "bake-test" gem "bake-test-external" gem 'benchmark-ips' gem 'http' + gem "async-container", "~> 0.15" + gem "rack-test" end diff --git a/gems/async-head.rb b/gems/async-head.rb index f9c56db..1044343 100644 --- a/gems/async-head.rb +++ b/gems/async-head.rb @@ -6,5 +6,6 @@ source 'https://rubygems.org' gemspec path: "../" +eval_gemfile "../gems.rb" gem 'async', git: "https://github.com/socketry/async" diff --git a/gems/async-v1.rb b/gems/async-v1.rb index 9d505c3..c09b65c 100644 --- a/gems/async-v1.rb +++ b/gems/async-v1.rb @@ -6,5 +6,6 @@ source 'https://rubygems.org' gemspec path: "../" +eval_gemfile "../gems.rb" gem 'async', '~> 1.0' diff --git a/lib/async/io.rb b/lib/async/io.rb index 683b7ed..22b7ddf 100644 --- a/lib/async/io.rb +++ b/lib/async/io.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2017-2023, by Samuel Williams. +# Copyright, 2017-2024, by Samuel Williams. require 'async' diff --git a/lib/async/io/endpoint.rb b/lib/async/io/endpoint.rb index 1e0db12..49a9f98 100644 --- a/lib/async/io/endpoint.rb +++ b/lib/async/io/endpoint.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2017-2023, by Samuel Williams. +# Copyright, 2017-2024, by Samuel Williams. # Copyright, 2019, by Olle Jonsson. require_relative 'address' diff --git a/lib/async/io/generic.rb b/lib/async/io/generic.rb index b748dd0..8a20137 100644 --- a/lib/async/io/generic.rb +++ b/lib/async/io/generic.rb @@ -3,6 +3,7 @@ # Released under the MIT License. # Copyright, 2017-2023, by Samuel Williams. # Copyright, 2021, by Aurora Nockert. +# Copyright, 2023, by Patrik Wenger. require 'async/wrapper' require 'forwardable' diff --git a/lib/async/io/shared_endpoint.rb b/lib/async/io/shared_endpoint.rb index c5dd76b..a929459 100644 --- a/lib/async/io/shared_endpoint.rb +++ b/lib/async/io/shared_endpoint.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2018-2023, by Samuel Williams. +# Copyright, 2018-2024, by Samuel Williams. # Copyright, 2019, by Olle Jonsson. require_relative 'endpoint' diff --git a/lib/async/io/ssl_endpoint.rb b/lib/async/io/ssl_endpoint.rb index b088ee7..b58da57 100644 --- a/lib/async/io/ssl_endpoint.rb +++ b/lib/async/io/ssl_endpoint.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2018-2023, by Samuel Williams. +# Copyright, 2018-2024, by Samuel Williams. # Copyright, 2019, by Olle Jonsson. require_relative 'host_endpoint' diff --git a/lib/async/io/stream.rb b/lib/async/io/stream.rb index b0523b3..baeebc8 100644 --- a/lib/async/io/stream.rb +++ b/lib/async/io/stream.rb @@ -4,6 +4,7 @@ # Copyright, 2017-2023, by Samuel Williams. # Copyright, 2018, by Janko Marohnić. # Copyright, 2021, by Aurora Nockert. +# Copyright, 2023, by Maruth Goyal. require_relative 'buffer' require_relative 'generic' diff --git a/lib/async/io/unix_endpoint.rb b/lib/async/io/unix_endpoint.rb index 3b586e8..e993a2d 100644 --- a/lib/async/io/unix_endpoint.rb +++ b/lib/async/io/unix_endpoint.rb @@ -3,6 +3,7 @@ # Released under the MIT License. # Copyright, 2019-2023, by Samuel Williams. # Copyright, 2019, by Olle Jonsson. +# Copyright, 2023, by Hasan Kumar. require_relative 'address_endpoint' diff --git a/lib/async/io/version.rb b/lib/async/io/version.rb index b6ecc54..8b9784c 100644 --- a/lib/async/io/version.rb +++ b/lib/async/io/version.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2017-2023, by Samuel Williams. +# Copyright, 2017-2024, by Samuel Williams. module Async module IO diff --git a/license.md b/license.md index 22d8d6f..e4486b9 100644 --- a/license.md +++ b/license.md @@ -1,7 +1,7 @@ # MIT License -Copyright, 2017-2023, by Samuel Williams. -Copyright, 2017-2021, by Olle Jonsson. +Copyright, 2017-2024, by Samuel Williams. +Copyright, 2017-2023, by Olle Jonsson. Copyright, 2018, by Janko Marohnić. Copyright, 2018, by Jiang Jinyang. Copyright, 2018, by Thibaut Girka. @@ -9,7 +9,10 @@ Copyright, 2019-2020, by Benoit Daloze. Copyright, 2020, by Cyril Roelandt. Copyright, 2020, by Bruno Sutic. Copyright, 2021, by Aurora Nockert. -Copyright, 2022, by Hal Brodigan. +Copyright, 2022-2023, by Hal Brodigan. +Copyright, 2023, by Hasan Kumar. +Copyright, 2023, by Maruth Goyal. +Copyright, 2023, by Patrik Wenger. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/readme.md b/readme.md index c2fbf52..4805fad 100644 --- a/readme.md +++ b/readme.md @@ -135,6 +135,14 @@ We welcome contributions to this project. 4. Push to the branch (`git push origin my-new-feature`). 5. Create new Pull Request. +### Developer Certificate of Origin + +This project uses the [Developer Certificate of Origin](https://developercertificate.org/). All contributors to this project must agree to this document to have their contributions accepted. + +### Contributor Covenant + +This project is governed by the [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms. + ## See Also - [async](https://github.com/socketry/async) — Asynchronous event-driven reactor. diff --git a/spec/async/io/generic_spec.rb b/spec/async/io/generic_spec.rb index 3054fff..d46c556 100644 --- a/spec/async/io/generic_spec.rb +++ b/spec/async/io/generic_spec.rb @@ -2,6 +2,7 @@ # Released under the MIT License. # Copyright, 2017-2023, by Samuel Williams. +# Copyright, 2023, by Patrik Wenger. require 'async/io' require 'async/clock' diff --git a/spec/async/io/shared_endpoint_spec.rb b/spec/async/io/shared_endpoint_spec.rb index 1827c0f..03333ec 100644 --- a/spec/async/io/shared_endpoint_spec.rb +++ b/spec/async/io/shared_endpoint_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true # Released under the MIT License. -# Copyright, 2018-2023, by Samuel Williams. +# Copyright, 2018-2024, by Samuel Williams. require 'async/io/host_endpoint' require 'async/io/shared_endpoint' diff --git a/spec/async/io/stream_spec.rb b/spec/async/io/stream_spec.rb index 0104a28..9b5f18c 100644 --- a/spec/async/io/stream_spec.rb +++ b/spec/async/io/stream_spec.rb @@ -5,6 +5,8 @@ # Copyright, 2018, by Janko Marohnić. # Copyright, 2019, by Benoit Daloze. # Copyright, 2021, by Aurora Nockert. +# Copyright, 2023, by Maruth Goyal. +# Copyright, 2023, by Olle Jonsson. require 'async/io' require 'async/io/socket' diff --git a/spec/async/io/unix_endpoint_spec.rb b/spec/async/io/unix_endpoint_spec.rb index ff4e58e..ac4fa73 100644 --- a/spec/async/io/unix_endpoint_spec.rb +++ b/spec/async/io/unix_endpoint_spec.rb @@ -2,6 +2,7 @@ # Released under the MIT License. # Copyright, 2019-2023, by Samuel Williams. +# Copyright, 2023, by Hasan Kumar. require 'async/io/unix_endpoint' require 'async/io/stream' From 1c4f93b2441745446bf40d29f928eecc8b0399da Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Wed, 17 Apr 2024 00:20:56 +1200 Subject: [PATCH 04/14] Bump patch version. --- lib/async/io/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/async/io/version.rb b/lib/async/io/version.rb index 8b9784c..adaf433 100644 --- a/lib/async/io/version.rb +++ b/lib/async/io/version.rb @@ -5,6 +5,6 @@ module Async module IO - VERSION = "1.42.0" + VERSION = "1.42.1" end end From af9164d3dc0062d58a75588552dfb3c459548ceb Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 23 Apr 2024 13:51:04 +1200 Subject: [PATCH 05/14] `Async::IO::Stream` can handle native IO. (#82) --- lib/async/io/stream.rb | 23 +++++++++++++++++++++-- spec/async/io/stream_spec.rb | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/lib/async/io/stream.rb b/lib/async/io/stream.rb index baeebc8..56a35e0 100644 --- a/lib/async/io/stream.rb +++ b/lib/async/io/stream.rb @@ -197,6 +197,10 @@ def connected? @io.connected? end + def readable? + @io.readable? + end + def closed? @io.closed? end @@ -246,6 +250,21 @@ def eof! private + def sysread(size, buffer) + while true + result = @io.read_nonblock(size, buffer, exception: false) + + case result + when :wait_readable + @io.wait_readable + when :wait_writable + @io.wait_writable + else + return result + end + end + end + # Fills the buffer from the underlying stream. def fill_read_buffer(size = @block_size) # We impose a limit because the underlying `read` system call can fail if we request too much data in one go. @@ -257,12 +276,12 @@ def fill_read_buffer(size = @block_size) flush if @read_buffer.empty? - if @io.read_nonblock(size, @read_buffer, exception: false) + if sysread(size, @read_buffer) # Console.logger.debug(self, name: "read") {@read_buffer.inspect} return true end else - if chunk = @io.read_nonblock(size, @input_buffer, exception: false) + if chunk = sysread(size, @input_buffer) @read_buffer << chunk # Console.logger.debug(self, name: "read") {@read_buffer.inspect} diff --git a/spec/async/io/stream_spec.rb b/spec/async/io/stream_spec.rb index 9b5f18c..b19bfdc 100644 --- a/spec/async/io/stream_spec.rb +++ b/spec/async/io/stream_spec.rb @@ -23,6 +23,26 @@ end end + context "native I/O", if: RUBY_VERSION >= "3.1" do + let(:sockets) do + @sockets = ::Socket.pair(::Socket::AF_UNIX, ::Socket::SOCK_STREAM) + end + + after do + @sockets.each(&:close) + end + + let(:io) {sockets.first} + subject {described_class.new(sockets.last)} + + it "can read data" do + io.write("Hello World") + io.close_write + + expect(subject.read).to be == "Hello World" + end + end + context "socket I/O" do let(:sockets) do @sockets = Async::IO::Socket.pair(Socket::AF_UNIX, Socket::SOCK_STREAM) From a7c9b6584ae1a9330b41bc63131c2ee97f340d12 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 23 Apr 2024 16:10:00 +1200 Subject: [PATCH 06/14] More compatibility with native sockets. --- lib/async/io/generic.rb | 4 ++++ lib/async/io/ssl_socket.rb | 12 ++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/async/io/generic.rb b/lib/async/io/generic.rb index 8a20137..a4076f2 100644 --- a/lib/async/io/generic.rb +++ b/lib/async/io/generic.rb @@ -192,6 +192,10 @@ def connected? !@io.closed? end + def readable? + @io.readable? + end + attr_accessor :timeout protected diff --git a/lib/async/io/ssl_socket.rb b/lib/async/io/ssl_socket.rb index bba1840..3659d7a 100644 --- a/lib/async/io/ssl_socket.rb +++ b/lib/async/io/ssl_socket.rb @@ -51,10 +51,14 @@ def initialize(socket, context) super else io = self.class.wrapped_klass.new(socket.to_io, context) - super(io, socket.reactor) - - # We detach the socket from the reactor, otherwise it's possible to add the file descriptor to the selector twice, which is bad. - socket.reactor = nil + if socket.respond_to?(:reactor) + super(io, socket.reactor) + + # We detach the socket from the reactor, otherwise it's possible to add the file descriptor to the selector twice, which is bad. + socket.reactor = nil + else + super(io) + end # This ensures that when the internal IO is closed, it also closes the internal socket: io.sync_close = true From 91ef29e5f31b673a79c11b93388eba6a8e064cfa Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 23 Apr 2024 16:13:48 +1200 Subject: [PATCH 07/14] Bump minor version. --- lib/async/io/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/async/io/version.rb b/lib/async/io/version.rb index adaf433..330d687 100644 --- a/lib/async/io/version.rb +++ b/lib/async/io/version.rb @@ -5,6 +5,6 @@ module Async module IO - VERSION = "1.42.1" + VERSION = "1.43.0" end end From 446a1c77e82a72868e8ff0b6ba0ac3e6c60dc7e4 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 23 Apr 2024 16:19:35 +1200 Subject: [PATCH 08/14] `IO#timeout` compatibility fix. Ruby < 3.2 doesn't provide `IO#timeout`. --- lib/async/io/ssl_socket.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/async/io/ssl_socket.rb b/lib/async/io/ssl_socket.rb index 3659d7a..8b26dd1 100644 --- a/lib/async/io/ssl_socket.rb +++ b/lib/async/io/ssl_socket.rb @@ -63,7 +63,9 @@ def initialize(socket, context) # This ensures that when the internal IO is closed, it also closes the internal socket: io.sync_close = true - @timeout = socket.timeout + if socket.respond_to?(:timeout) + @timeout = socket.timeout + end end end From 6c063c1cccf5988e49fad48d623ef8a2d9b92363 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 23 Apr 2024 16:20:05 +1200 Subject: [PATCH 09/14] Bump patch version. --- lib/async/io/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/async/io/version.rb b/lib/async/io/version.rb index 330d687..a673a42 100644 --- a/lib/async/io/version.rb +++ b/lib/async/io/version.rb @@ -5,6 +5,6 @@ module Async module IO - VERSION = "1.43.0" + VERSION = "1.43.1" end end From 965ff6d34a5637e804a26eba4d8f39459fed8011 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 23 Apr 2024 22:41:42 +1200 Subject: [PATCH 10/14] Copy timeout if possible. --- lib/async/io/ssl_socket.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/async/io/ssl_socket.rb b/lib/async/io/ssl_socket.rb index 8b26dd1..00f5ba1 100644 --- a/lib/async/io/ssl_socket.rb +++ b/lib/async/io/ssl_socket.rb @@ -118,8 +118,12 @@ def listen(*args) @server.listen(*args) end - def accept(task: Task.current, **options) - peer, address = @server.accept(**options) + def accept(task: Task.current, timeout: nil) + peer, address = @server.accept + + if timeout and peer.respond_to?(:timeout=) + peer.timeout = timeout + end wrapper = SSLSocket.new(peer, @context) From 268c0b564e9904ad49a4d8d1435279003721c297 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 23 Apr 2024 23:01:17 +1200 Subject: [PATCH 11/14] Bump patch version. --- lib/async/io/version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/async/io/version.rb b/lib/async/io/version.rb index a673a42..3dd45b0 100644 --- a/lib/async/io/version.rb +++ b/lib/async/io/version.rb @@ -5,6 +5,6 @@ module Async module IO - VERSION = "1.43.1" + VERSION = "1.43.2" end end From 7d5657bc78ba9704b33c943ed96453b96e2a2094 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 23 Apr 2024 23:55:53 +1200 Subject: [PATCH 12/14] May be native IO. Don't try to clear `reactor`. --- lib/async/io/shared_endpoint.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/async/io/shared_endpoint.rb b/lib/async/io/shared_endpoint.rb index a929459..a259359 100644 --- a/lib/async/io/shared_endpoint.rb +++ b/lib/async/io/shared_endpoint.rb @@ -24,7 +24,10 @@ def self.bound(endpoint, backlog: Socket::SOMAXCONN, close_on_exec: false, **opt end server.close_on_exec = close_on_exec - server.reactor = nil + + if server.respond_to?(:reactor=) + server.reactor = nil + end end return self.new(endpoint, wrappers) @@ -35,7 +38,10 @@ def self.connected(endpoint, close_on_exec: false) wrapper = endpoint.connect wrapper.close_on_exec = close_on_exec - wrapper.reactor = nil + + if wrapper.respond_to?(:reactor=) + wrapper.reactor = nil + end return self.new(endpoint, [wrapper]) end From 6b5dc269b4526460bbb4caa2d33cf324b686bf13 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Tue, 7 May 2024 22:03:53 +1200 Subject: [PATCH 13/14] Add tea.xyz constitution file. --- tea.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 tea.yaml diff --git a/tea.yaml b/tea.yaml new file mode 100644 index 0000000..cfafe79 --- /dev/null +++ b/tea.yaml @@ -0,0 +1,6 @@ +# https://tea.xyz/what-is-this-file +--- +version: 1.0.0 +codeOwners: + - '0x03d7E2c0cf7813867DDb318674B66CC53B8497dA' +quorum: 1 From efad25529371b109fe008f84f4f1ed09963b5dd4 Mon Sep 17 00:00:00 2001 From: Samuel Williams Date: Fri, 30 Aug 2024 09:02:16 +1200 Subject: [PATCH 14/14] Add deprecation warning. --- readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/readme.md b/readme.md index 4805fad..1b41e2c 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,8 @@ # Async::IO +> [!CAUTION] +> This library is deprecated and should not be used in new projects. Instead, you should use for the endpoint-related functionality, and for stream/buffering functionality. + Async::IO provides builds on [async](https://github.com/socketry/async) and provides asynchronous wrappers for `IO`, `Socket`, and related classes. [![Development Status](https://github.com/socketry/async-io/workflows/Test/badge.svg)](https://github.com/socketry/async-io/actions?workflow=Test)