只有对 repo 有绝对话语权的人才能提大几千行的 PR。
brew --prefix openssl@3
rvm install 3.3.1 --with-openssl-dir=$(brew --prefix openssl)
我有一个练手项目是 rails + turbo + stimulus 写绝大部分页面,交互复杂页面用 svelte。
稍微看了一些回复,发现很多人都不知道 turbo 基本没有给 end user 的 api,甚至不知道 turbo 是干什么的就来评论
科普一下,对 turbo 库的使用者来说,turbo 是用 js 开发的还是 ts 开发的根本没区别,基本没有 js 方法给你调用。
叠甲:对于 turbo contributors 来说是有资格愤怒的。
比较好奇怎么做大家才觉得妥当?核心团队做出 break change 的决定后,然后花几个月时间在社区说服所有人然后再进行?
而且这是 turbo 7 升 8 的"break" change,任何库升大版本都会有很多不兼容旧版本的改动,都会有不同意见,很正常的事。
ENFP-A 每个字母都出现过了。
catch/throw
ActionCable 一般通过有 pubsub 功能的组件实现 broadcast,比如 redis https://redis.io/docs/manual/pubsub/。
每一个 rails web 进程都保存自己 websocket 连接以及这些连接都订阅了哪些 channel(actioncable 里的 channel)。 同时 web 进程也 subscribe 了 redis actioncable 的 channel(redis 的 channel,跟 actioncable 的 channel 不是一个东西)。
worker 里面调用 broadcast,实际是向 redis 的 actioncable channel 发一条信息,向“xx channel 广播 yy message”。 web 进程收到“xx channel 广播 yy message”,检查自己进程里有没有连接订阅过 xx channel,如果有的话就发送"yy message”。
ruby 3.2 a[5,1]
就是nil
了
https://rubyapi.org/2.7/o/string#method-i-5B-5D
Additionally, an empty string is returned when the starting index for a character range is at the end of the string.
https://guides.rubyonrails.org/active_support_instrumentation.html#cache-read-active-support 靠 APM 工具或者自己统计 hit/total
rails new app --minimal
先说一下结论免得你排查走弯路:抛ActiveRecord::ConnectionTimeoutError
错误的话 100% 是因为你的业务线程数跟 ActiveRecord
的本地数据库连接池大小不匹配(错误信息could not obtain a connection from the pool within %0.3f seconds (waited %0.3f seconds); all pooled connections were in use
, https://github.com/rails/rails/blob/v7.0.4/activerecord/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb#L124), ActiveRecord::ConnectionTimeoutError
的注释:
Raised when a connection could not be obtained within the connection acquisition timeout period: because max connections in pool are in use.
可能的原因有
如果是数据库原因不能建立新的数据库连接,抛的错是 ActiveRecord::ConnectionNotEstablished,错误信息来自于具体数据库连接的库,例如 pg 的是: https://github.com/rails/rails/blob/v7.0.4/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L87
我好奇的是你的 ActiveRecord pool 设成 300 居然还能 checkout 不了新的数据库连接,我猜测你的应用应该有多种 rails 进程(比如 puma,worker,grpc 三种进程),报错的的那个进程 pool size 不一定是 300。
方便的话把堆栈也发一下(业务代码的堆栈可以过滤掉)
建议查一下 grpc 进程的数据库连接池大小。连接池大小一般都是通过环境变量来的,可能 grpc 进程的大小不是 300。 如果你是直连 postgres(不通过 pgbouncer 一类的中间件),连接池满的话 pg 不可能不到 70 个链接。
先看一下ActiveRecord::Base.connection_pool.size
。这个数是你 rails 进程的最大并发数。
rpc 也有一个线程池,我目前开了 200
相当于 200 个线程共享 ActiveRecord::Base.connection_pool.size 个数据库链接,如果 size 太小肯定不够用,从 pool 里 checkout 一个 connection 肯定会超时。
另外连 pg 建议通过 pgbouncer 连。
这个问题一般是应用线程抢不到数据库连接池里的链接,跟数据库负载关系不大。
我想了一种折中方案,就是通过实际调用 service 来准备数据,然后把这些数据 dump 一份,保存来用作 mock,这样 service 改变这个 dump 也不会变,可以很好地满足他想要隔离测试的想法。
因为你在 config 或者 initializer 中有数据库操作。assets:precompile 本身不需要连接数据库的,看一下错误堆栈,找到连数据库的代码,想办法避免启动的时候执行。
写测试。
require 'thread'
t1, t2, t3 = nil, nil, nil
def download
sleep rand(5..10)
end
t1 = Thread.new do
t = Time.now
download
t2.raise "STOP"
t3.raise "STOP"
puts "t1 download done."
rescue
puts "abort t1"
ensure
# teardown
puts "t1 duration: #{Time.now - t}"
end
t2 = Thread.new do
t = Time.now
download
t1.raise "STOP"
t3.raise "STOP"
puts "t2 download done."
rescue
puts "abort t2"
ensure
# teardown
puts "t2 duration: #{Time.now - t}"
end
t3 = Thread.new do
t = Time.now
download
t1.raise "STOP"
t2.raise "STOP"
puts "t3 download done."
rescue
puts "abort t3"
ensure
# teardown
puts "t3 duration: #{Time.now - t}"
end
[t1, t2, t3].map(&:join)
Ruby 可以通过Thread#raise
向另外一个线程抛异常来中断另一个线程。
turbo 启用的情况下,create action 要 render 一个 create.turbo_stream.erb, 在 create.turbo_stream.erb 用 turbo 相关标签声明你要替换/新增那些 html。
turbo 关闭(传统模式)是整页重新 render,开启则是服务端返回一些 html 片段,页面只局部更新。
ruby 做算法题在耗时上有劣势。同样的算法用其他语言写可以过。
form tag 上加上data-turbo="false"
试试
不依赖 DOM 是事实,无关好坏。
回答一下"Hotwire 依赖 DOM"的问题:答案是否定的。 Hotwire 的核心是 Turbo,使用 Turbo 不需要写 javascript,所以也不依赖 DOM。
The heart of Hotwire is Turbo. A set of complementary techniques for speeding up page changes and form submissions, dividing complex pages into components, and stream partial page updates over WebSocket. All without writing any JavaScript at all. And designed from the start to integrate perfectly with native hybrid applications for iOS and Android.
所谓依赖 DOM 的是 Stimulus,但是 Stimulus 只占 Hotwire 非常小的一部分
While Turbo usually takes care of at least 80% of the interactivity that traditionally would have required JavaScript, there are still cases where a dash of custom code is required. Stimulus makes this easy with a HTML-centric approach to state and wiring.
Stimulus 在 Hotwire 中是可以被 react/vue 等前端库替代的。Stimulus 本身就很轻量,也不难,是 Hotwire 需要的功能的最小集。
Hotwire 还有一个重要模块是 Strada,Strada 是 Hotwire web 应用可以转换成 hybrid 的 mobile app,加上 Strada 才是完整的 Hotwire,一套代码可以应用在 web/ios/android 三端。(但是一直跳票)
Hotwire 不仅不依赖 DOM,还是一种减少 javascript 使用的开发模式。