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
ways • Structured names • Foo::Bar::Baz • Major scenario: • Top-level “User” or “Configuration” classes (gems, apps, etc) • Two apps in a process (in the context of “Modular monolith”)
globally, from anywhere • A single Module/Class instance • Example: Oj.default_options = {symbol_keys: true} • A single Module/Class definition • Process global open classes (monkey patches) • A single set of constants • A single set of global variables
can’t be loaded • Application libraries and library dependencies • App uses X, and Y ver 2 • X depends on Y ver 1 • “Dependency hell” • App uses A and B • A depends on C ver 1 • B depends on C ver 2 App C ver 1 C ver 2 A B App Y ver 1 X Y ver 2
• “on write” approach • Libraries (gems) need to be written in the namespace manner (on write) • Update all gems in rubygems…? 😱 • “on read” approach • Libraries/Apps are loaded into spaces when loaded/require (on read) • We can use all gems as-is, with bene fi ts of namespaces
of Module • Use existing mechanism of load(file, module) • Load .rb fi les (A::B) under a module (M) → M::A::B • See also: “Multiverse Ruby” (RubyKaigi 2023, @shioyama) • Modify C API to de fi ne class/module: class_alloc (in class.c) • Create classes/modules (X) under a namespace (NS) → NS::X • To support extensions (.so/.dll/.bundle)
fi les can be loaded 2 times or more • Loading extensions (.so/.dll/.bundle) in namespace • Copying the extension fi le to a tmp dir with PID & namespace pre fi x: my_ext.so → 515_160_my_ext.so • Using RTLD_LOCAL only when RUBY_NAMESPACE=1 • Hide exported (C) symbols to other extensions
can modify built-in classes/modules • For monkey patches in namespace: class Object; def blank?; … • In other NSs: Object without #blank? • Class/Module de fi nition: classext (struct: rb_classext_t) • super, method table, constant table, instance variables, subclasses, … • Switching classext realizes a class with di ff erent de fi nitions! 🤪 (Thanks to @_ko1 and @mametter)
User’s Class/Module Class/Module Example Object String Kernel JSON ActiveSupport MyAppUser Root Namespace ✅ ✅ ✅ Main Namespace Namespace A Namespace B Before Running User Scripts ✅ classext readable/writable
Applications server based on Namespace • namespace per app • multiple apps are mounted using namespace • 2 or more applications on a single tenant (process) • Without con fl icts/collisions by namespace • Especially for development without containers on laptops App Server Namespace Web app Request Response Routing
is in namespace If there is a dependency con fl ict • Your apps can be deployed before the gem’s update! • IMPORTANT: • We MUST keep the “healthy, updated” rubygems society • How to avoid moral hazard? App C ver 1 C ver 2 A B NEED DISCUSSIONS