Add the BsaDomainRefresh entity (#2250)

Add the BsaDomainRefresh class which tracks the refresh actions.

The refresh actions checks for changes in the set of registered and
reserved domains, which are called unblockables to BSA.
This commit is contained in:
Weimin Yu 2023-12-13 16:08:37 -05:00 committed by GitHub
parent 8d793b2349
commit c73f7a6bd3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 182 additions and 0 deletions

View file

@ -0,0 +1,117 @@
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.bsa.persistence;
import static google.registry.bsa.persistence.BsaDomainRefresh.Stage.MAKE_DIFF;
import com.google.common.base.Objects;
import google.registry.model.CreateAutoTimestamp;
import google.registry.model.UpdateAutoTimestamp;
import google.registry.persistence.VKey;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import org.joda.time.DateTime;
/**
* Records of completed and ongoing refresh actions, which recomputes the set of unblockable domains
* and reports changes to BSA.
*
* <p>The refresh action only handles registered and reserved domain names. Invalid names only
* change status when the IDN tables change, and will be handled by a separate tool when it happens.
*/
@Entity
public class BsaDomainRefresh {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long jobId;
@Column(nullable = false)
CreateAutoTimestamp creationTime = CreateAutoTimestamp.create(null);
@Column(nullable = false)
UpdateAutoTimestamp updateTime = UpdateAutoTimestamp.create(null);
@Column(nullable = false)
@Enumerated(EnumType.STRING)
Stage stage = MAKE_DIFF;
BsaDomainRefresh() {}
long getJobId() {
return jobId;
}
DateTime getCreationTime() {
return creationTime.getTimestamp();
}
/**
* Returns the starting time of this job as a string, which can be used as folder name on GCS when
* storing download data.
*/
public String getJobName() {
return "refresh-" + getCreationTime().toString();
}
public Stage getStage() {
return this.stage;
}
BsaDomainRefresh setStage(Stage stage) {
this.stage = stage;
return this;
}
VKey<BsaDomainRefresh> vKey() {
return vKey(this);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof BsaDomainRefresh)) {
return false;
}
BsaDomainRefresh that = (BsaDomainRefresh) o;
return Objects.equal(jobId, that.jobId)
&& Objects.equal(creationTime, that.creationTime)
&& Objects.equal(updateTime, that.updateTime)
&& stage == that.stage;
}
@Override
public int hashCode() {
return Objects.hashCode(jobId, creationTime, updateTime, stage);
}
static VKey vKey(BsaDomainRefresh bsaDomainRefresh) {
return VKey.create(BsaDomainRefresh.class, bsaDomainRefresh.jobId);
}
enum Stage {
MAKE_DIFF,
APPLY_DIFF,
REPORT_REMOVALS,
REPORT_ADDITIONS;
}
}

View file

@ -38,6 +38,7 @@
<mapping-file>META-INF/orm.xml</mapping-file> <mapping-file>META-INF/orm.xml</mapping-file>
<class>google.registry.bsa.persistence.BsaDomainRefresh</class>
<class>google.registry.bsa.persistence.BsaDownload</class> <class>google.registry.bsa.persistence.BsaDownload</class>
<class>google.registry.bsa.persistence.BsaLabel</class> <class>google.registry.bsa.persistence.BsaLabel</class>
<class>google.registry.bsa.persistence.BsaDomainInUse</class> <class>google.registry.bsa.persistence.BsaDomainInUse</class>

View file

@ -0,0 +1,54 @@
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.bsa.persistence;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.bsa.persistence.BsaDomainRefresh.Stage.MAKE_DIFF;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static org.joda.time.DateTimeZone.UTC;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationWithCoverageExtension;
import google.registry.testing.FakeClock;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit test for {@link BsaDomainRefresh}. */
public class BsaDomainRefreshTest {
protected FakeClock fakeClock = new FakeClock(DateTime.now(UTC));
@RegisterExtension
final JpaIntegrationWithCoverageExtension jpa =
new JpaTestExtensions.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
@Test
void saveJob() {
BsaDomainRefresh persisted =
tm().transact(() -> tm().getEntityManager().merge(new BsaDomainRefresh()));
assertThat(persisted.jobId).isNotNull();
assertThat(persisted.creationTime.getTimestamp()).isEqualTo(fakeClock.nowUtc());
assertThat(persisted.stage).isEqualTo(MAKE_DIFF);
}
@Test
void loadJobByKey() {
BsaDomainRefresh persisted =
tm().transact(() -> tm().getEntityManager().merge(new BsaDomainRefresh()));
assertThat(tm().transact(() -> tm().loadByKey(BsaDomainRefresh.vKey(persisted))))
.isEqualTo(persisted);
}
}

View file

@ -17,6 +17,7 @@ package google.registry.schema.integration;
import static com.google.common.truth.Truth.assert_; import static com.google.common.truth.Truth.assert_;
import google.registry.bsa.persistence.BsaDomainInUseTest; import google.registry.bsa.persistence.BsaDomainInUseTest;
import google.registry.bsa.persistence.BsaDomainRefreshTest;
import google.registry.bsa.persistence.BsaDownloadTest; import google.registry.bsa.persistence.BsaDownloadTest;
import google.registry.bsa.persistence.BsaLabelTest; import google.registry.bsa.persistence.BsaLabelTest;
import google.registry.model.billing.BillingBaseTest; import google.registry.model.billing.BillingBaseTest;
@ -86,6 +87,7 @@ import org.junit.runner.RunWith;
AllocationTokenTest.class, AllocationTokenTest.class,
BillingBaseTest.class, BillingBaseTest.class,
BsaDomainInUseTest.class, BsaDomainInUseTest.class,
BsaDomainRefreshTest.class,
BsaDownloadTest.class, BsaDownloadTest.class,
BsaLabelTest.class, BsaLabelTest.class,
BulkPricingPackageTest.class, BulkPricingPackageTest.class,

View file

@ -93,6 +93,14 @@
primary key (label, tld) primary key (label, tld)
); );
create table "BsaDomainRefresh" (
job_id bigserial not null,
creation_time timestamptz not null,
stage text not null,
update_timestamp timestamptz,
primary key (job_id)
);
create table "BsaDownload" ( create table "BsaDownload" (
job_id bigserial not null, job_id bigserial not null,
block_list_checksums text not null, block_list_checksums text not null,