mirror of
https://github.com/google/nomulus.git
synced 2025-05-13 16:07:15 +02:00
Fix soft delete for possible double-map of domain
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=167040455
This commit is contained in:
parent
ccc51daa9f
commit
fa447ce37e
2 changed files with 51 additions and 2 deletions
|
@ -57,6 +57,7 @@ import google.registry.util.PipelineUtils;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
import org.joda.time.Duration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all prober DomainResources and their subordinate history entries, poll messages, and
|
* Deletes all prober DomainResources and their subordinate history entries, poll messages, and
|
||||||
|
@ -116,6 +117,23 @@ public class DeleteProberDataAction implements Runnable {
|
||||||
private static final DnsQueue dnsQueue = DnsQueue.create();
|
private static final DnsQueue dnsQueue = DnsQueue.create();
|
||||||
private static final long serialVersionUID = -7724537393697576369L;
|
private static final long serialVersionUID = -7724537393697576369L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum amount of time we allow a prober domain to be in use.
|
||||||
|
*
|
||||||
|
* In practice, the prober's connection will time out well before this duration. This includes a
|
||||||
|
* decent buffer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final Duration DOMAIN_USED_DURATION = Duration.standardHours(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum amount of time we want a domain to be "soft deleted".
|
||||||
|
*
|
||||||
|
* The domain has to remain soft deleted for at least enough time for the DNS task to run and
|
||||||
|
* remove it from DNS itself. This is probably on the order of minutes.
|
||||||
|
*/
|
||||||
|
private static final Duration SOFT_DELETE_DELAY = Duration.standardHours(1);
|
||||||
|
|
||||||
private final ImmutableSet<String> proberRoidSuffixes;
|
private final ImmutableSet<String> proberRoidSuffixes;
|
||||||
private final Boolean isDryRun;
|
private final Boolean isDryRun;
|
||||||
private final String registryAdminClientId;
|
private final String registryAdminClientId;
|
||||||
|
@ -144,6 +162,9 @@ public class DeleteProberDataAction implements Runnable {
|
||||||
|
|
||||||
private void deleteDomain(final Key<DomainBase> domainKey) {
|
private void deleteDomain(final Key<DomainBase> domainKey) {
|
||||||
final DomainBase domainBase = ofy().load().key(domainKey).now();
|
final DomainBase domainBase = ofy().load().key(domainKey).now();
|
||||||
|
|
||||||
|
DateTime now = DateTime.now(UTC);
|
||||||
|
|
||||||
if (domainBase == null) {
|
if (domainBase == null) {
|
||||||
// Depending on how stale Datastore indexes are, we can get keys to resources that are
|
// Depending on how stale Datastore indexes are, we can get keys to resources that are
|
||||||
// already deleted (e.g. by a recent previous invocation of this mapreduce). So ignore them.
|
// already deleted (e.g. by a recent previous invocation of this mapreduce). So ignore them.
|
||||||
|
@ -161,7 +182,7 @@ public class DeleteProberDataAction implements Runnable {
|
||||||
getContext().incrementCounter("skipped, NIC domain");
|
getContext().incrementCounter("skipped, NIC domain");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (domain.getCreationTime().isAfter(DateTime.now(UTC).minusHours(1))) {
|
if (now.isBefore(domain.getCreationTime().plus(DOMAIN_USED_DURATION))) {
|
||||||
getContext().incrementCounter("skipped, domain too new");
|
getContext().incrementCounter("skipped, domain too new");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +196,7 @@ public class DeleteProberDataAction implements Runnable {
|
||||||
// successfully soft-delete the domain (thus leaving its DNS entry published). We soft-delete
|
// successfully soft-delete the domain (thus leaving its DNS entry published). We soft-delete
|
||||||
// it now so that the DNS entry can be handled. The domain will then be hard-deleted the next
|
// it now so that the DNS entry can be handled. The domain will then be hard-deleted the next
|
||||||
// time the mapreduce is run.
|
// time the mapreduce is run.
|
||||||
if (EppResourceUtils.isActive(domain, DateTime.now(UTC))) {
|
if (EppResourceUtils.isActive(domain, now)) {
|
||||||
if (isDryRun) {
|
if (isDryRun) {
|
||||||
logger.infofmt("Would soft-delete the active domain: %s", domainKey);
|
logger.infofmt("Would soft-delete the active domain: %s", domainKey);
|
||||||
} else {
|
} else {
|
||||||
|
@ -184,6 +205,13 @@ public class DeleteProberDataAction implements Runnable {
|
||||||
getContext().incrementCounter("domains soft-deleted");
|
getContext().incrementCounter("domains soft-deleted");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// If the domain isn't active, we want to make sure it hasn't been active for "a while" before
|
||||||
|
// deleting it. This prevents accidental double-map with the same key from immediately
|
||||||
|
// deleting active domains
|
||||||
|
if (now.isBefore(domain.getDeletionTime().plus(SOFT_DELETE_DELAY))) {
|
||||||
|
getContext().incrementCounter("skipped, domain too recently soft deleted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final Key<EppResourceIndex> eppIndex = Key.create(EppResourceIndex.create(domainKey));
|
final Key<EppResourceIndex> eppIndex = Key.create(EppResourceIndex.create(domainKey));
|
||||||
final Key<? extends ForeignKeyIndex<?>> fki = ForeignKeyIndex.createKey(domain);
|
final Key<? extends ForeignKeyIndex<?>> fki = ForeignKeyIndex.createKey(domain);
|
||||||
|
|
|
@ -79,6 +79,10 @@ public class DeleteProberDataActionTest extends MapreduceTestCase<DeleteProberDa
|
||||||
createTld("oa-canary.test", "OACANT");
|
createTld("oa-canary.test", "OACANT");
|
||||||
persistResource(Registry.get("oa-canary.test").asBuilder().setTldType(TldType.TEST).build());
|
persistResource(Registry.get("oa-canary.test").asBuilder().setTldType(TldType.TEST).build());
|
||||||
|
|
||||||
|
resetAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resetAction() {
|
||||||
action = new DeleteProberDataAction();
|
action = new DeleteProberDataAction();
|
||||||
action.mrRunner = makeDefaultRunner();
|
action.mrRunner = makeDefaultRunner();
|
||||||
action.response = new FakeResponse();
|
action.response = new FakeResponse();
|
||||||
|
@ -140,6 +144,23 @@ public class DeleteProberDataActionTest extends MapreduceTestCase<DeleteProberDa
|
||||||
assertDnsTasksEnqueued("blah.ib-any.test");
|
assertDnsTasksEnqueued("blah.ib-any.test");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_activeDomain_doubleMapSoftDeletes() throws Exception {
|
||||||
|
DomainResource domain = persistResource(
|
||||||
|
newDomainResource("blah.ib-any.test")
|
||||||
|
.asBuilder()
|
||||||
|
.setCreationTimeForTest(DateTime.now(UTC).minusYears(1))
|
||||||
|
.build());
|
||||||
|
runMapreduce();
|
||||||
|
DateTime timeAfterDeletion = DateTime.now(UTC);
|
||||||
|
resetAction();
|
||||||
|
runMapreduce();
|
||||||
|
assertThat(loadByForeignKey(DomainResource.class, "blah.ib-any.test", timeAfterDeletion))
|
||||||
|
.isNull();
|
||||||
|
assertThat(ofy().load().entity(domain).now().getDeletionTime()).isLessThan(timeAfterDeletion);
|
||||||
|
assertDnsTasksEnqueued("blah.ib-any.test");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test_recentlyCreatedDomain_isntDeletedYet() throws Exception {
|
public void test_recentlyCreatedDomain_isntDeletedYet() throws Exception {
|
||||||
persistResource(
|
persistResource(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue