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)
|
def initialize(provisioner: nil)
|
||||||
@provisioner = provisioner || NodeProvisioner.new
|
@provisioner = provisioner || NodeProvisioner.new
|
||||||
|
@provisioned_this_round = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def reconcile!
|
def reconcile!
|
||||||
@@ -154,6 +155,7 @@ module Streams
|
|||||||
|
|
||||||
scale_in_candidates.each do |node|
|
scale_in_candidates.each do |node|
|
||||||
next if keep_as_warm_spare?(node)
|
next if keep_as_warm_spare?(node)
|
||||||
|
next if @provisioned_this_round.include?(node.id)
|
||||||
|
|
||||||
safe_scale_in!(node)
|
safe_scale_in!(node)
|
||||||
actions << :"scale_in_#{node.slug}"
|
actions << :"scale_in_#{node.slug}"
|
||||||
@@ -191,6 +193,7 @@ module Streams
|
|||||||
end
|
end
|
||||||
|
|
||||||
def provision_overflow!
|
def provision_overflow!
|
||||||
|
node =
|
||||||
case self.class.kind
|
case self.class.kind
|
||||||
when "cloud"
|
when "cloud"
|
||||||
raise NodeProvisioner::Error, "Cloud autoscale disabilitato (STREAM_AUTOSCALE_ALLOW_CLOUD / HCLOUD_TOKEN)" unless self.class.allow_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
|
else
|
||||||
@provisioner.provision_lab!
|
@provisioner.provision_lab!
|
||||||
end
|
end
|
||||||
|
@provisioned_this_round << node.id if node
|
||||||
|
node
|
||||||
end
|
end
|
||||||
|
|
||||||
def safe_scale_in!(node)
|
def safe_scale_in!(node)
|
||||||
|
|||||||
@@ -91,6 +91,55 @@ RSpec.describe Streams::Autoscaler do
|
|||||||
end
|
end
|
||||||
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
|
it "scales in an idle overflow node when warm spare is not required" do
|
||||||
with_env(
|
with_env(
|
||||||
"STREAM_AUTOSCALE_ENABLED" => "1",
|
"STREAM_AUTOSCALE_ENABLED" => "1",
|
||||||
|
|||||||
Reference in New Issue
Block a user