Skip to content

Commit

Permalink
Merge branch 'clean-caches-2' into 'master'
Browse files Browse the repository at this point in the history
Don't set exists watches if it is not necessary

See merge request vostok-libraries/servicediscovery!3
  • Loading branch information
Гладышева Татьяна Владимировна committed Mar 11, 2024
2 parents b107340 + c11976a commit 4dd7ec8
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using NUnit.Framework;
using Vostok.Commons.Testing;
using Vostok.ServiceDiscovery.Abstractions.Models;
using Vostok.ServiceDiscovery.Models;
using Vostok.ServiceDiscovery.ServiceLocatorStorage;
using Vostok.ZooKeeper.Client.Abstractions;

Expand All @@ -20,7 +19,7 @@ public void Should_track_application_properties()
CreateApplicationNode("default", "application");
CreateReplicaNode(new ReplicaInfo("default", "application", "https://github.com/vostok"));

using (var storage = GetApplicationsStorage())
using (var storage = GetApplicationsStorage(out _))
{
for (var times = 0; times < 10; times++)
{
Expand All @@ -46,7 +45,7 @@ public void Should_track_application_replicas()
CreateEnvironmentNode("default");
CreateApplicationNode("default", "application");

using (var storage = GetApplicationsStorage())
using (var storage = GetApplicationsStorage(out _))
{
var expectedReplicas = new List<Uri>();

Expand All @@ -69,7 +68,7 @@ public void Should_return_null_without_application()
{
CreateEnvironmentNode("default");

using (var storage = GetApplicationsStorage())
using (var storage = GetApplicationsStorage(out _))
{
ShouldReturnImmediately(storage, "default", "application", null);

Expand All @@ -85,7 +84,7 @@ public void Should_return_empty_list_without_replicas()
CreateEnvironmentNode("default");
CreateApplicationNode("default", "application");

using (var storage = GetApplicationsStorage())
using (var storage = GetApplicationsStorage(out _))
{
ShouldReturnImmediately(storage, "default", "application", ServiceTopology.Build(new Uri[0], null));

Expand All @@ -106,7 +105,7 @@ public void Should_store_multiple_environments_and_applications()
CreateApplicationNode("environment2", "application1", new Dictionary<string, string> {{"key", "2/1"}});
CreateApplicationNode("environment2", "application2", new Dictionary<string, string> {{"key", "2/2"}});

using (var storage = GetApplicationsStorage())
using (var storage = GetApplicationsStorage(out _))
{
ShouldReturnImmediately(
storage,
Expand Down Expand Up @@ -134,7 +133,7 @@ public void Should_works_disconnected()
CreateApplicationNode("default", "application");
CreateReplicaNode(new ReplicaInfo("default", "application", "https://github.com/vostok"));

using (var storage = GetApplicationsStorage())
using (var storage = GetApplicationsStorage(out _))
{
var properties = new Dictionary<string, string>
{
Expand Down Expand Up @@ -162,7 +161,7 @@ public void Should_not_update_after_dispose()
CreateApplicationNode("default", "application", new Dictionary<string, string> {{"key", "value1"}});
CreateReplicaNode(new ReplicaInfo("default", "application", "https://github.com/vostok"));

using (var storage = GetApplicationsStorage())
using (var storage = GetApplicationsStorage(out _))
{
var expected = ServiceTopology.Build(new List<Uri> {new Uri("https://github.com/vostok")}, new Dictionary<string, string> {{"key", "value1"}});
ShouldReturnImmediately(storage, "default", "application", expected);
Expand All @@ -182,7 +181,7 @@ public void Should_not_update_to_invalid_application_properties()
CreateApplicationNode("default", "application", new Dictionary<string, string> {{"key", "value"}});
CreateReplicaNode(new ReplicaInfo("default", "application", "https://github.com/vostok"));

using (var storage = GetApplicationsStorage())
using (var storage = GetApplicationsStorage(out _))
{
var expected = ServiceTopology.Build(new List<Uri> {new Uri("https://github.com/vostok")}, new Dictionary<string, string> {{"key", "value"}});
ShouldReturnImmediately(storage, "default", "application", expected);
Expand All @@ -201,7 +200,7 @@ public void UpdateAll_should_force_update()
CreateEnvironmentNode("default");
CreateApplicationNode("default", "application");

using (var storage = GetApplicationsStorage())
using (var storage = GetApplicationsStorage(out _))
{
var expectedReplicas = new List<Uri>();

Expand All @@ -224,6 +223,104 @@ public void UpdateAll_should_force_update()
}
}

[Test]
public void Should_delete_application_from_cache_if_app_and_env_nodes_were_deleted_when_observation_of_deleted_apps_is_disabled()
{
const string environment = "environment1";
const string app = "application1";

var expectedTopology = ServiceTopology.Build(new Uri[0], new Dictionary<string, string> {{"key", "1/1"}});

using (var storage = GetApplicationsStorage(out var envStorage, observeNonExistentApplications: false))
{
for (var i = 0; i < 10; i++)
{
CreateEnvironmentNode(environment);
CreateApplicationNode(environment, app, new Dictionary<string, string> {{"key", "1/1"}});

envStorage.Get(environment).Should().BeEquivalentTo(new EnvironmentInfo(environment, null, null));

ShouldReturnImmediately(
storage,
environment,
app,
expectedTopology);

DeleteApplicationNode(environment, app);
DeleteEnvironmentNode(environment);

envStorage.UpdateAll();
storage.UpdateAll();

storage.Contains(environment, app).Should().BeFalse();
}
}
}

[Test]
public void Should_not_delete_application_from_cache_when_env_exists_and_observation_of_deleted_apps_is_disabled()
{
const string environment = "environment1";
const string app = "application1";

CreateEnvironmentNode(environment);
CreateApplicationNode(environment, app, new Dictionary<string, string> {{"key", "1/1"}});

using (var storage = GetApplicationsStorage(out var envStorage, observeNonExistentApplications: false))
{
var expectedTopology = ServiceTopology.Build(new Uri[0], new Dictionary<string, string> {{"key", "1/1"}});
ShouldReturnImmediately(
storage,
environment,
app,
expectedTopology);

envStorage.Get(environment).Should().BeEquivalentTo(new EnvironmentInfo(environment, null, null));

DeleteApplicationNode(environment, app);

envStorage.UpdateAll();
envStorage.Contains(environment).Should().BeTrue();
storage.UpdateAll();

storage.Contains(environment, app).Should().BeTrue();
}
}

[Test]
public void Should_not_delete_application_from_cache_when_observation_of_deleted_apps_is_disabled_and_client_disconnected()
{
const string environment = "environment1";
const string app = "application1";
CreateEnvironmentNode(environment);
CreateApplicationNode(environment, app, new Dictionary<string, string> {{"key", "1/1"}});

using (var storage = GetApplicationsStorage(out var envStorage, observeNonExistentApplications: false))
{
var expectedTopology = ServiceTopology.Build(new Uri[0], new Dictionary<string, string> {{"key", "1/1"}});
ShouldReturnImmediately(
storage,
environment,
app,
expectedTopology);

envStorage.Get(environment).Should().BeEquivalentTo(new EnvironmentInfo(environment, null, null));

Ensemble.Stop();

envStorage.UpdateAll();
envStorage.Contains(environment).Should().BeTrue();
storage.UpdateAll();

storage.Contains(environment, app).Should().BeTrue();
ShouldReturnImmediately(
storage,
environment,
app,
expectedTopology);
}
}

private static void ShouldReturn(ApplicationsStorage storage, string environment, string application, ServiceTopology topology)
{
Action assertion = () => { ShouldReturnImmediately(storage, environment, application, topology); };
Expand All @@ -235,9 +332,10 @@ private static void ShouldReturnImmediately(ApplicationsStorage storage, string
storage.Get(environment, application).ServiceTopology.Should().BeEquivalentTo(topology);
}

private ApplicationsStorage GetApplicationsStorage()
private ApplicationsStorage GetApplicationsStorage(out EnvironmentsStorage envStorage, bool observeNonExistentApplications = true)
{
return new ApplicationsStorage(ZooKeeperClient, PathHelper, EventsQueue, Log);
envStorage = new EnvironmentsStorage(ZooKeeperClient, PathHelper, EventsQueue, observeNonExistentApplications, Log);
return new ApplicationsStorage(ZooKeeperClient, PathHelper, EventsQueue, observeNonExistentApplications, envStorage, Log);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using FluentAssertions;
using Vostok.Commons.Testing;
using Vostok.ServiceDiscovery.Abstractions.Models;
using Vostok.ServiceDiscovery.ServiceLocatorStorage;

namespace Vostok.ServiceDiscovery.Tests.ServiceLocatorStorage;

internal class EnvironmentStorage_TestsBase : TestsBase
{
protected static void ShouldReturn(EnvironmentsStorage storage, string name, EnvironmentInfo info)
{
Action assertion = () => { ShouldReturnImmediately(storage, name, info); };
assertion.ShouldPassIn(DefaultTimeout);
}

protected static void ShouldReturnImmediately(EnvironmentsStorage storage, string name, EnvironmentInfo info)
{
storage.Get(name).Should().BeEquivalentTo(info);
}

protected EnvironmentsStorage GetEnvironmentsStorage(bool observeNonExistentEnvironment = true)
{
return new EnvironmentsStorage(ZooKeeperClient, PathHelper, EventsQueue, observeNonExistentEnvironment, Log);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using NUnit.Framework;
using FluentAssertions;
using Vostok.ServiceDiscovery.Abstractions.Models;

namespace Vostok.ServiceDiscovery.Tests.ServiceLocatorStorage;

[TestFixture]
internal class EnvironmentsStorageWithObserveFlag_Tests : EnvironmentStorage_TestsBase
{
[Test]
public void Should_not_delete_environment_from_cache_if_node_was_deleted_when_observation_of_deleted_apps_is_enabled()
{
using (var storage = GetEnvironmentsStorage(observeNonExistentEnvironment: true))
{
CreateEnvironmentNode("default", "parent");

var expectedInfo = new EnvironmentInfo("default", "parent", null);
storage.Get("default").Should().BeEquivalentTo(expectedInfo);

DeleteEnvironmentNode("default");
storage.UpdateAll();
storage.Contains("default").Should().BeTrue();
storage.Get("default").Should().BeNull();

CreateEnvironmentNode("default", "parent");
ShouldReturn(storage, "default", expectedInfo);
}
}

[Test]
public void Should_not_delete_environment_from_cache_when_observation_of_deleted_apps_is_disabled_and_client_disconnected()
{
using (var storage = GetEnvironmentsStorage(observeNonExistentEnvironment: false))
{
CreateEnvironmentNode("default", "parent");

var expectedInfo = new EnvironmentInfo("default", "parent", null);
ShouldReturnImmediately(storage, "default", expectedInfo);

Ensemble.Stop();

storage.UpdateAll();
storage.Contains("default").Should().BeTrue();
ShouldReturnImmediately(storage, "default", expectedInfo);
}
}

[Test]
public void Should_delete_environment_from_cache_if_node_was_deleted_when_observation_of_deleted_apps_is_disabled()
{
var expectedInfo = new EnvironmentInfo("default", "parent", null);

using (var storage = GetEnvironmentsStorage(observeNonExistentEnvironment: false))
{
for (var i = 0; i < 10; i++)
{
CreateEnvironmentNode("default", "parent");

ShouldReturnImmediately(storage, "default", expectedInfo);

DeleteEnvironmentNode("default");
storage.UpdateAll();
storage.Contains("default").Should().BeFalse();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using System.Collections.Generic;
using NUnit.Framework;
using Vostok.Commons.Testing;
using Vostok.ServiceDiscovery.Abstractions.Models;
using Vostok.ServiceDiscovery.Models;
using Vostok.ServiceDiscovery.ServiceLocatorStorage;
using Vostok.ZooKeeper.Client.Abstractions;

namespace Vostok.ServiceDiscovery.Tests.ServiceLocatorStorage
{
[TestFixture]
internal class EnvironmentsStorage_Tests : TestsBase
internal class EnvironmentsStorage_Tests : EnvironmentStorage_TestsBase
{
[Test]
public void Should_track_environment_parent_with_properties()
Expand Down Expand Up @@ -154,21 +149,5 @@ public void UpdateAll_should_force_update()
}
}
}

private static void ShouldReturn(EnvironmentsStorage storage, string name, EnvironmentInfo info)
{
Action assertion = () => { ShouldReturnImmediately(storage, name, info); };
assertion.ShouldPassIn(DefaultTimeout);
}

private static void ShouldReturnImmediately(EnvironmentsStorage storage, string name, EnvironmentInfo info)
{
storage.Get(name).Should().BeEquivalentTo(info);
}

private EnvironmentsStorage GetEnvironmentsStorage()
{
return new EnvironmentsStorage(ZooKeeperClient, PathHelper, EventsQueue, Log);
}
}
}
2 changes: 2 additions & 0 deletions Vostok.ServiceDiscovery/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,5 @@ Vostok.ServiceDiscovery.ServiceLocatorSettings.ZooKeeperNodesPathEscaper.get ->
Vostok.ServiceDiscovery.ServiceLocatorSettings.ZooKeeperNodesPathEscaper.set -> void
Vostok.ServiceDiscovery.ServiceLocatorSettings.ZooKeeperNodesPrefix.get -> string
Vostok.ServiceDiscovery.ServiceLocatorSettings.ZooKeeperNodesPrefix.set -> void
Vostok.ServiceDiscovery.ServiceLocatorSettings.ObserveNonExistentApplications.get -> bool
Vostok.ServiceDiscovery.ServiceLocatorSettings.ObserveNonExistentApplications.set -> void
5 changes: 2 additions & 3 deletions Vostok.ServiceDiscovery/ServiceLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ public ServiceLocator(
pathHelper = new ServiceDiscoveryPathHelper(this.settings.ZooKeeperNodesPrefix, this.settings.ZooKeeperNodesPathEscaper);

eventsQueue = new ActionsQueue(this.log);
environmentsStorage = new EnvironmentsStorage(zooKeeperClient, pathHelper, eventsQueue, log);
applicationsStorage = new ApplicationsStorage(zooKeeperClient, pathHelper, eventsQueue, log);

environmentsStorage = new EnvironmentsStorage(zooKeeperClient, pathHelper, eventsQueue, this.settings.ObserveNonExistentApplications, log);
applicationsStorage = new ApplicationsStorage(zooKeeperClient, pathHelper, eventsQueue, this.settings.ObserveNonExistentApplications, environmentsStorage, log);
}

/// <inheritdoc />
Expand Down
2 changes: 2 additions & 0 deletions Vostok.ServiceDiscovery/ServiceLocatorSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ public class ServiceLocatorSettings
public IZooKeeperPathEscaper ZooKeeperNodesPathEscaper { get; set; } = ZooKeeperPathEscaper.Instance;

public TimeSpan IterationPeriod { get; set; } = 5.Seconds();

public bool ObserveNonExistentApplications { get; set; } = true;
}
}
Loading

0 comments on commit 4dd7ec8

Please sign in to comment.