Evita scale-in del nodo appena creato nello stesso reconcile.
Con IDLE_MINUTES=0 (o race stretta) lo scale-out veniva annullato subito; lo smoke AutoscalerJob Cloud su collaudo ora completa scale-out e scale-in. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -131,6 +131,7 @@ module Streams
|
||||
|
||||
def initialize(provisioner: nil)
|
||||
@provisioner = provisioner || NodeProvisioner.new
|
||||
@provisioned_this_round = []
|
||||
end
|
||||
|
||||
def reconcile!
|
||||
@@ -154,6 +155,7 @@ module Streams
|
||||
|
||||
scale_in_candidates.each do |node|
|
||||
next if keep_as_warm_spare?(node)
|
||||
next if @provisioned_this_round.include?(node.id)
|
||||
|
||||
safe_scale_in!(node)
|
||||
actions << :"scale_in_#{node.slug}"
|
||||
@@ -191,6 +193,7 @@ module Streams
|
||||
end
|
||||
|
||||
def provision_overflow!
|
||||
node =
|
||||
case self.class.kind
|
||||
when "cloud"
|
||||
raise NodeProvisioner::Error, "Cloud autoscale disabilitato (STREAM_AUTOSCALE_ALLOW_CLOUD / HCLOUD_TOKEN)" unless self.class.allow_cloud?
|
||||
@@ -199,6 +202,8 @@ module Streams
|
||||
else
|
||||
@provisioner.provision_lab!
|
||||
end
|
||||
@provisioned_this_round << node.id if node
|
||||
node
|
||||
end
|
||||
|
||||
def safe_scale_in!(node)
|
||||
|
||||
@@ -91,6 +91,55 @@ RSpec.describe Streams::Autoscaler do
|
||||
end
|
||||
end
|
||||
|
||||
it "does not scale in a node provisioned in the same reconcile round" do
|
||||
with_env(
|
||||
"STREAM_AUTOSCALE_ENABLED" => "1",
|
||||
"STREAM_AUTOSCALE_SOFT_FREE_SLOTS" => "2",
|
||||
"STREAM_AUTOSCALE_WARM_SPARE" => "0",
|
||||
"STREAM_AUTOSCALE_IDLE_MINUTES" => "0",
|
||||
"STREAM_AUTOSCALE_KIND" => "lab",
|
||||
"STREAM_AUTOSCALE_MAX_NODES" => "5",
|
||||
"STREAM_CLOUD_PROVIDER" => "local_lab",
|
||||
"STREAM_DNS_PROVIDER" => "lab",
|
||||
"STREAM_NODE_HOME_MAX_PUBLISHERS" => "2",
|
||||
"MEDIAMTX_API_URL" => "http://mtx-home:9997",
|
||||
"MEDIAMTX_RTMP_URL" => "rtmp://home.example:1935",
|
||||
"HLS_PUBLIC_URL" => "https://home.example/hls"
|
||||
) do
|
||||
home = Streams::NodeRegistry.ensure_home_from_env!
|
||||
user = User.create!(email: "same@example.com", name: "S", password: "Password123", role: "coach")
|
||||
club = Club.create!(name: "Same", sport: "volleyball")
|
||||
team = club.teams.create!(name: "T", sport: "volleyball", slug: "same-t")
|
||||
match = team.matches.create!(opponent_name: "X", scheduled_at: 1.hour.from_now)
|
||||
2.times do
|
||||
StreamSession.create!(match: match, user: user, platform: "matchlivetv", status: "live", stream_node: home)
|
||||
end
|
||||
|
||||
provisioner = instance_double(Streams::NodeProvisioner)
|
||||
created = nil
|
||||
allow(provisioner).to receive(:provision_lab!) do
|
||||
created = StreamNode.create!(
|
||||
slug: "ingest-lab-new",
|
||||
hostname: "new.lab",
|
||||
role: "lab",
|
||||
status: "ready",
|
||||
provider: "local",
|
||||
rtmp_base_url: "rtmp://h:1935",
|
||||
hls_base_url: "https://h/hls",
|
||||
api_base_url: "http://h:9997",
|
||||
max_publishers: 4,
|
||||
max_relays: 2
|
||||
)
|
||||
end
|
||||
expect(provisioner).not_to receive(:decommission!)
|
||||
|
||||
result = described_class.reconcile!(provisioner: provisioner)
|
||||
expect(result.actions).to include(:scale_out)
|
||||
expect(result.actions.map(&:to_s)).not_to include("scale_in_ingest-lab-new")
|
||||
expect(StreamNode.find_by(slug: "ingest-lab-new")).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
it "scales in an idle overflow node when warm spare is not required" do
|
||||
with_env(
|
||||
"STREAM_AUTOSCALE_ENABLED" => "1",
|
||||
|
||||
Reference in New Issue
Block a user