Slide 1

Slide 1 text

Satoshi Tagomori (@tagomoris) 2024/08/31 RubyKaigi 2024 follow up event Namespace, Now and Then The State of Namespace

Slide 2

Slide 2 text

@tagomoris Satoshi Tagomori Maintainer/Founder: OSS: Fluentd, MessagePack, 
 Norikra, Woothee, …
 Event: ISUCON Service: Pathtraq

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Namespace Separating apps/libs into isolated spaces • Load apps/libs in a space • Hide changes from apps/libs in a namespace to other spaces • Run methods de fi ned in a space with de fi nitions in the space

Slide 5

Slide 5 text

Before Namespace: Global Only All classes/modules are shared in the entire Ruby process Ruby Process Application Code App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7)

Slide 6

Slide 6 text

Collision: 2 versions of 1 library cause errors Ruby Process Library Code DB::Client (v3) 😵 Application Code App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7) Before Namespace: Global Only

Slide 7

Slide 7 text

Ruby Process Namespace Load apps/libs in a space Namespace Application Code App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7)

Slide 8

Slide 8 text

Ruby Process Namespace Hide changes from apps/libs in a namespace to other spaces Namespace Application Code App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7) Library Code DB::Client (v3) 😀

Slide 9

Slide 9 text

Ruby Process Namespace Run methods de fi ned in a space with de fi nitions in the space Namespace Application Code App::Func User Library Code DB::Client (v2) Library Code ActiveSupport (v7) Namespace Library Code DB::Client (v3) Namespace Application Code App::Func2 User Library Code ActiveSupport (v6) Application Code call call call

Slide 10

Slide 10 text

at RubyKaigi 2024 Did it work? • Demo code failed with SEGV (just once! 🤪) • ‘test-all’ stopped in the middle with SEGV

Slide 11

Slide 11 text

at Jul 1 😵💫

Slide 12

Slide 12 text

at the End of Aug, 2024 Does it work? • Demo code SHOULD run successfully! • ‘test-all’ runs to the end! • 2 failures, 1 error • 2 failures: new failures after the last rebase • 1 error: SEGV about (probably) subclasses with GC.compact

Slide 13

Slide 13 text

Namespace design updates Types of Namespaces • Before RubyKaigi 2024 • Root namespace • Main namespace • (Other) namespaces • After RubyKaigi 2024 • Root namespace • Builtin namespace • (User namespaces) • Main namespace • Optional namespaces

Slide 14

Slide 14 text

Types of Namespaces (cont.) Seeing is Believing Root Builtin (For built-in class/module methods written in Ruby) Main Optional 1 Optional 2 …… User for built-in
 classes/modules for user
 scripts

Slide 15

Slide 15 text

Loading .rb into builtin namespace RubyGems is in the box! • Classes/Modules available without any #require
 
 SHOULD be in the root (or builtin) namespace • RubyGems should be in the root/builtin namespace • RubyGems requires its .rb fi les … What happens?

Slide 16

Slide 16 text

User What Happens with #require Without RubyGems Root Builtin Main Optional 1 Optional 2 …… Application Code Class/Module Methods require ‘foo’ Kernel#require Call #require Load .rb in
 the caller namespace
 (main)

Slide 17

Slide 17 text

User What Happens with #require With RubyGems Root Builtin Main Optional 1 Optional 2 …… Ruby Code Class/Module Methods require ‘foo’ Kernel#gem_original_require Kernel#require Which one is
 the “desired” caller?

Slide 18

Slide 18 text

User What Happens with #require With RubyGems, by RubyGems .rb code Root Builtin Main Optional 1 Optional 2 …… Ruby Code Class/Module Methods require ‘bar’ Kernel#gem_original_require Kernel#require RubyGems requires
 fi les to be loaded
 into the builtin namespace!

Slide 19

Slide 19 text

User What Happens with #require With RubyGems, and RubyGems .rb code Root Builtin Main Optional 1 Optional 2 …… Ruby Code Class/Module Methods Kernel#gem_original_require Kernel#require require ‘foo’ Call #require
 (caller is main)

Slide 20

Slide 20 text

User What Happens with #require With RubyGems, and RubyGems .rb code Root Builtin Main Optional 1 Optional 2 …… Ruby Code Class/Module Methods Kernel#gem_original_require Kernel#require require ‘bar’ The .rb code for
 Kernel#require
 executes any .rb
 code
 (caller is main) require ‘foo’

Slide 21

Slide 21 text

User What Happens with #require With RubyGems, and RubyGems .rb code Root Builtin Main Optional 1 Optional 2 …… Ruby Code Class/Module Methods Kernel#gem_original_require Kernel#require require ‘foo’ require ‘bar’ The .rb code
 requires any fi le
 (caller is builtin)

Slide 22

Slide 22 text

User What Happens with #require With RubyGems, and RubyGems .rb code Root Builtin Main Optional 1 Optional 2 …… Ruby Code Class/Module Methods Kernel#gem_original_require Kernel#require require ‘foo’ RubyGems #require
 calls the original #require
 in the root namespace
 (caller is builtin) require ‘bar’

Slide 23

Slide 23 text

User What Happens with #require With RubyGems, and RubyGems .rb code Root Builtin Main Optional 1 Optional 2 …… Ruby Code Class/Module Methods Kernel#gem_original_require Kernel#require require ‘foo’ The original #require
 loads the fi le into
 the builtin namespace
 (caller is builtin) require ‘bar’

Slide 24

Slide 24 text

User What Happens with #require With RubyGems, and RubyGems .rb code Root Builtin Main Optional 1 Optional 2 …… Ruby Code Class/Module Methods Kernel#gem_original_require Kernel#require RubyGems #require
 continues the original
 #require call for the main
 (caller is main) require ‘foo’ require ‘bar’

Slide 25

Slide 25 text

User What Happens with #require With RubyGems, and RubyGems .rb code Root Builtin Main Optional 1 Optional 2 …… Ruby Code Class/Module Methods Kernel#gem_original_require Kernel#require Finally, the target .rb fi le
 is loaded into the main
 (caller is main) require ‘foo’ require ‘bar’

Slide 26

Slide 26 text

😳

Slide 27

Slide 27 text

Builtin Namespace Implicit Refinements User Namespace Implicit Mix-ins

Slide 28

Slide 28 text

Namespace is still WIP, Mostly about just 1 SEGV. Stay tuned til Ruby 3.4! (or …?)