Add missing foreign key constraints (#845)

* Add missing foreign key constraints

* Fix failed unit tests
This commit is contained in:
Shicong Huang 2020-11-09 10:55:29 -05:00 committed by GitHub
parent 7097b0f5e6
commit 420f3bf380
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 6756 additions and 4864 deletions

View file

@ -217,7 +217,7 @@ class InitSqlPipelineTest {
GracePeriodStatus.ADD,
"4-COM",
fakeClock.nowUtc().plusDays(1),
"registrar",
"TheRegistrar",
null))
.build());
exportDir = store.export(exportRootDir.getAbsolutePath(), ALL_KINDS, ImmutableSet.of());

View file

@ -17,6 +17,7 @@ package google.registry.model.domain;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.SqlHelper.assertThrowForeignKeyViolation;
import static google.registry.testing.SqlHelper.saveRegistrar;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
@ -45,30 +46,29 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.model.transfer.ContactTransferData;
import google.registry.model.transfer.DomainTransferData;
import google.registry.persistence.VKey;
import google.registry.persistence.transaction.JpaTestRules;
import google.registry.persistence.transaction.JpaTestRules.JpaIntegrationWithCoverageExtension;
import google.registry.testing.DatastoreEntityExtension;
import google.registry.testing.AppEngineExtension;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.FakeClock;
import google.registry.testing.TestSqlOnly;
import java.util.Arrays;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Verify that we can store/retrieve DomainBase objects from a SQL database. */
@DualDatabaseTest
public class DomainBaseSqlTest {
protected FakeClock fakeClock = new FakeClock(DateTime.now(UTC));
@RegisterExtension
@Order(value = 1)
DatastoreEntityExtension datastoreEntityExtension = new DatastoreEntityExtension();
@RegisterExtension
JpaIntegrationWithCoverageExtension jpa =
new JpaTestRules.Builder().withClock(fakeClock).buildIntegrationWithCoverageExtension();
public final AppEngineExtension appEngine =
AppEngineExtension.builder()
.withDatastoreAndCloudSql()
.enableJpaEntityCoverageCheck(true)
.withClock(fakeClock)
.build();
private DomainBase domain;
private DomainHistory historyEntry;
@ -132,7 +132,7 @@ public class DomainBaseSqlTest {
contact2 = makeContact("contact_id2");
}
@Test
@TestSqlOnly
void testDomainBasePersistence() {
persistDomain();
@ -144,7 +144,7 @@ public class DomainBaseSqlTest {
});
}
@Test
@TestSqlOnly
void testHostForeignKeyConstraints() {
assertThrowForeignKeyViolation(
() ->
@ -158,7 +158,7 @@ public class DomainBaseSqlTest {
}));
}
@Test
@TestSqlOnly
void testContactForeignKeyConstraints() {
assertThrowForeignKeyViolation(
() ->
@ -171,7 +171,7 @@ public class DomainBaseSqlTest {
}));
}
@Test
@TestSqlOnly
void testResaveDomain_succeeds() {
persistDomain();
jpaTm()
@ -189,7 +189,7 @@ public class DomainBaseSqlTest {
});
}
@Test
@TestSqlOnly
void testModifyGracePeriod_setEmptyCollectionSuccessfully() {
persistDomain();
jpaTm()
@ -209,7 +209,7 @@ public class DomainBaseSqlTest {
});
}
@Test
@TestSqlOnly
void testModifyGracePeriod_setNullCollectionSuccessfully() {
persistDomain();
jpaTm()
@ -228,7 +228,7 @@ public class DomainBaseSqlTest {
});
}
@Test
@TestSqlOnly
void testModifyGracePeriod_addThenRemoveSuccessfully() {
persistDomain();
jpaTm()
@ -305,7 +305,7 @@ public class DomainBaseSqlTest {
});
}
@Test
@TestSqlOnly
void testModifyGracePeriod_removeThenAddSuccessfully() {
persistDomain();
jpaTm()
@ -347,7 +347,7 @@ public class DomainBaseSqlTest {
});
}
@Test
@TestSqlOnly
void testModifyDsData_addThenRemoveSuccessfully() {
persistDomain();
DelegationSignerData extraDsData =
@ -391,8 +391,9 @@ public class DomainBaseSqlTest {
});
}
@Test
@TestSqlOnly
void testUpdates() {
createTld("com");
jpaTm()
.transact(
() -> {
@ -423,6 +424,7 @@ public class DomainBaseSqlTest {
}
private void persistDomain() {
createTld("com");
jpaTm()
.transact(
() -> {
@ -442,8 +444,9 @@ public class DomainBaseSqlTest {
});
}
@Test
@TestSqlOnly
void persistDomainWithCompositeVKeys() {
createTld("com");
jpaTm()
.transact(
() -> {
@ -572,8 +575,9 @@ public class DomainBaseSqlTest {
assertThat(persisted.getGracePeriods()).isEqualTo(gracePeriods);
}
@Test
@TestSqlOnly
void persistDomainWithLegacyVKeys() {
createTld("com");
jpaTm()
.transact(
() -> {

View file

@ -20,10 +20,10 @@ import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableO
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.newContactResourceWithRoid;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.newHostResourceWithRoid;
import static google.registry.testing.SqlHelper.saveRegistrar;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.collect.ImmutableSet;
@ -41,22 +41,19 @@ import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestOfyOnly;
import google.registry.testing.TestSqlOnly;
/** Tests for {@link DomainHistory}. */
@DualDatabaseTest
public class DomainHistoryTest extends EntityTestCase {
DomainHistoryTest() {
super(JpaEntityCoverageCheck.ENABLED);
}
@BeforeEach
void beforeEach() {
saveRegistrar("TheRegistrar");
}
@Test
@TestSqlOnly
void testPersistence() {
DomainBase domain = createDomainWithContactsAndHosts();
DomainHistory domainHistory = createDomainHistory(domain);
@ -71,7 +68,7 @@ public class DomainHistoryTest extends EntityTestCase {
});
}
@Test
@TestSqlOnly
void testLegacyPersistence_nullResource() {
DomainBase domain = createDomainWithContactsAndHosts();
DomainHistory domainHistory =
@ -92,7 +89,7 @@ public class DomainHistoryTest extends EntityTestCase {
});
}
@Test
@TestOfyOnly
void testOfyPersistence() {
HostResource host = newHostResourceWithRoid("ns1.example.com", "host1");
ContactResource contact = newContactResourceWithRoid("contactId", "contact1");
@ -128,6 +125,7 @@ public class DomainHistoryTest extends EntityTestCase {
}
static DomainBase createDomainWithContactsAndHosts() {
createTld("tld");
HostResource host = newHostResourceWithRoid("ns1.example.com", "host1");
ContactResource contact = newContactResourceWithRoid("contactId", "contact1");

View file

@ -17,10 +17,10 @@ package google.registry.model.history;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.newContactResourceWithRoid;
import static google.registry.testing.DatastoreHelper.newHostResourceWithRoid;
import static google.registry.testing.SqlHelper.saveRegistrar;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static java.nio.charset.StandardCharsets.UTF_8;
@ -40,34 +40,32 @@ import google.registry.model.reporting.DomainTransactionRecord;
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestSqlOnly;
/** Tests to check {@link HistoryEntry} + its subclasses' transitions to/from Datastore/SQL. */
@DualDatabaseTest
public class LegacyHistoryObjectTest extends EntityTestCase {
public LegacyHistoryObjectTest() {
super(JpaEntityCoverageCheck.ENABLED);
}
@BeforeEach
void beforeEach() {
saveRegistrar("TheRegistrar");
}
@Test
@TestSqlOnly
void testFullConversion_contact() {
// Create+save an old contact HistoryEntry, reload it, and verify it's a proper ContactHistory
ContactResource contact = newContactResourceWithRoid("contactId", "contact1");
HistoryEntry legacyHistoryEntry = historyEntryBuilderFor(contact).build();
tm().transact(() -> tm().insert(legacyHistoryEntry));
ofyTm().transact(() -> ofyTm().insert(legacyHistoryEntry));
// In Datastore, we will save it as HistoryEntry but retrieve it as ContactHistory
long historyEntryId = legacyHistoryEntry.getId();
HistoryEntry fromObjectify =
tm().transact(
ofyTm()
.transact(
() ->
tm().load(
ofyTm()
.load(
VKey.create(
HistoryEntry.class,
historyEntryId,
@ -96,19 +94,22 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
.isEqualTo(legacyHistoryFromSql.getParentVKey().getSqlKey());
}
@Test
@TestSqlOnly
void testFullConversion_domain() {
createTld("foobar");
// Create+save an old domain HistoryEntry, reload it, and verify it's a proper DomainHistory
DomainBase domain = DomainHistoryTest.createDomainWithContactsAndHosts();
HistoryEntry legacyHistoryEntry = historyEntryForDomain(domain);
tm().transact(() -> tm().insert(legacyHistoryEntry));
ofyTm().transact(() -> ofyTm().insert(legacyHistoryEntry));
// In Datastore, we will save it as HistoryEntry but retrieve it as DomainHistory
long historyEntryId = legacyHistoryEntry.getId();
HistoryEntry fromObjectify =
tm().transact(
ofyTm()
.transact(
() ->
tm().load(
ofyTm()
.load(
VKey.create(
HistoryEntry.class,
historyEntryId,
@ -140,19 +141,21 @@ public class LegacyHistoryObjectTest extends EntityTestCase {
.isEqualTo(nullToEmpty(legacyHistoryFromSql.getNsHosts()));
}
@Test
@TestSqlOnly
void testFullConversion_host() {
// Create+save an old host HistoryEntry, reload it, and verify it's a proper HostHistory
HostResource host = newHostResourceWithRoid("hs1.example.com", "host1");
HistoryEntry legacyHistoryEntry = historyEntryBuilderFor(host).build();
tm().transact(() -> tm().insert(legacyHistoryEntry));
ofyTm().transact(() -> ofyTm().insert(legacyHistoryEntry));
// In Datastore, we will save it as HistoryEntry but retrieve it as HostHistory
long historyEntryId = legacyHistoryEntry.getId();
HistoryEntry fromObjectify =
tm().transact(
ofyTm()
.transact(
() ->
tm().load(
ofyTm()
.load(
VKey.create(
HistoryEntry.class,
historyEntryId,

View file

@ -15,13 +15,12 @@
package google.registry.model.poll;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.persistActiveContact;
import static google.registry.testing.DatastoreHelper.persistResource;
import static google.registry.testing.SqlHelper.saveRegistrar;
import static java.nio.charset.StandardCharsets.UTF_8;
import google.registry.model.EntityTestCase;
@ -31,10 +30,14 @@ import google.registry.model.domain.Period;
import google.registry.model.eppcommon.Trid;
import google.registry.model.reporting.HistoryEntry;
import google.registry.persistence.VKey;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestOfyAndSql;
import google.registry.testing.TestOfyOnly;
import google.registry.testing.TestSqlOnly;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link PollMessage}. */
@DualDatabaseTest
public class PollMessageTest extends EntityTestCase {
private DomainBase domain;
@ -64,7 +67,8 @@ public class PollMessageTest extends EntityTestCase {
.setBySuperuser(false)
.setReason("reason")
.setRequestedByRegistrar(false)
.build());
.build()
.toChildHistoryEntity());
oneTime =
new PollMessage.OneTime.Builder()
.setId(100L)
@ -83,35 +87,9 @@ public class PollMessageTest extends EntityTestCase {
.setAutorenewEndTime(fakeClock.nowUtc().plusDays(365))
.setTargetId("foobar.foo")
.build();
jpaTm()
.transact(
() -> {
saveRegistrar("TheRegistrar");
jpaTm().insert(contact);
jpaTm().insert(domain);
jpaTm().insert(historyEntry.toChildHistoryEntity());
});
}
@Test
void testCloudSqlPersistenceOneTime() {
jpaTm().transact(() -> jpaTm().insert(oneTime));
PollMessage.OneTime persisted =
jpaTm().transact(() -> jpaTm().load(VKey.createSql(PollMessage.OneTime.class, oneTime.id)));
assertThat(persisted).isEqualTo(oneTime);
}
@Test
void testCloudSqlPersistenceAutorenew() {
jpaTm().transact(() -> jpaTm().insert(autoRenew));
PollMessage.Autorenew persisted =
jpaTm()
.transact(
() -> jpaTm().load(VKey.createSql(PollMessage.Autorenew.class, autoRenew.id)));
assertThat(persisted).isEqualTo(autoRenew);
}
@Test
@TestSqlOnly
void testCloudSqlSupportForPolymorphicVKey() {
jpaTm().transact(() -> jpaTm().insert(oneTime));
PollMessage persistedOneTime =
@ -126,7 +104,7 @@ public class PollMessageTest extends EntityTestCase {
assertThat(persistedAutoRenew).isEqualTo(autoRenew);
}
@Test
@TestOfyAndSql
void testPersistenceOneTime() {
PollMessage.OneTime pollMessage =
persistResource(
@ -136,10 +114,10 @@ public class PollMessageTest extends EntityTestCase {
.setMsg("Test poll message")
.setParent(historyEntry)
.build());
assertThat(ofy().load().entity(pollMessage).now()).isEqualTo(pollMessage);
assertThat(tm().transact(() -> tm().load(pollMessage))).isEqualTo(pollMessage);
}
@Test
@TestOfyAndSql
void testPersistenceAutorenew() {
PollMessage.Autorenew pollMessage =
persistResource(
@ -151,10 +129,10 @@ public class PollMessageTest extends EntityTestCase {
.setAutorenewEndTime(fakeClock.nowUtc().plusDays(365))
.setTargetId("foobar.foo")
.build());
assertThat(ofy().load().entity(pollMessage).now()).isEqualTo(pollMessage);
assertThat(tm().transact(() -> tm().load(pollMessage))).isEqualTo(pollMessage);
}
@Test
@TestOfyOnly
void testIndexingAutorenew() throws Exception {
PollMessage.Autorenew pollMessage =
persistResource(

View file

@ -17,23 +17,42 @@ package google.registry.model.reporting;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.testing.DatastoreHelper.createTlds;
import static google.registry.testing.DatastoreHelper.newDomainBase;
import static google.registry.testing.DatastoreHelper.persistActiveContact;
import static google.registry.testing.DatastoreHelper.persistResource;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import google.registry.model.EntityTestCase;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DomainBase;
import google.registry.model.reporting.Spec11ThreatMatch.ThreatType;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestSqlOnly;
import org.joda.time.LocalDate;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link Spec11ThreatMatchDao}. */
@DualDatabaseTest
public class Spec11ThreatMatchDaoTest extends EntityTestCase {
private static final LocalDate TODAY = new LocalDate(2020, 8, 4);
private static final LocalDate YESTERDAY = new LocalDate(2020, 8, 3);
private DomainBase todayComDomain;
private DomainBase todayOrgDomain;
private DomainBase yesterdayComDomain;
private DomainBase yesterdayOrgDomain;
@BeforeEach
void setUp() {
createTlds("com", "org");
ContactResource contact = persistActiveContact("jd1234");
todayComDomain = persistResource(newDomainBase("today.com", contact));
todayOrgDomain = persistResource(newDomainBase("today.org", contact));
yesterdayComDomain = persistResource(newDomainBase("yesterday.com", contact));
yesterdayOrgDomain = persistResource(newDomainBase("yesterday.org", contact));
jpaTm()
.transact(
() -> {
@ -42,7 +61,7 @@ public class Spec11ThreatMatchDaoTest extends EntityTestCase {
});
}
@Test
@TestSqlOnly
void testDeleteEntriesByDate() {
// Verify that all entries with the date TODAY were removed
jpaTm()
@ -66,7 +85,7 @@ public class Spec11ThreatMatchDaoTest extends EntityTestCase {
});
}
@Test
@TestSqlOnly
void testLoadEntriesByDate() {
jpaTm()
.transact(
@ -82,23 +101,25 @@ public class Spec11ThreatMatchDaoTest extends EntityTestCase {
private ImmutableList<Spec11ThreatMatch> getThreatMatchesYesterday() {
return ImmutableList.of(
createThreatMatch("yesterday.com", YESTERDAY),
createThreatMatch("yesterday.org", YESTERDAY));
createThreatMatch("yesterday.com", yesterdayComDomain.getRepoId(), YESTERDAY),
createThreatMatch("yesterday.org", yesterdayOrgDomain.getRepoId(), YESTERDAY));
}
private ImmutableList<Spec11ThreatMatch> getThreatMatchesToday() {
return ImmutableList.of(
createThreatMatch("today.com", TODAY), createThreatMatch("today.org", TODAY));
createThreatMatch("today.com", todayComDomain.getRepoId(), TODAY),
createThreatMatch("today.org", todayOrgDomain.getRepoId(), TODAY));
}
private Spec11ThreatMatch createThreatMatch(String domainName, LocalDate date) {
private Spec11ThreatMatch createThreatMatch(
String domainName, String domainRepoId, LocalDate date) {
return new Spec11ThreatMatch()
.asBuilder()
.setThreatTypes(ImmutableSet.of(ThreatType.MALWARE))
.setCheckDate(date)
.setDomainName(domainName)
.setRegistrarId("Example Registrar")
.setDomainRepoId("1-COM")
.setRegistrarId("TheRegistrar")
.setDomainRepoId(domainRepoId)
.build();
}
}

View file

@ -30,13 +30,16 @@ import google.registry.model.domain.DomainBase;
import google.registry.model.host.HostResource;
import google.registry.model.transfer.ContactTransferData;
import google.registry.persistence.VKey;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestOfyAndSql;
import google.registry.testing.TestSqlOnly;
import org.joda.time.LocalDate;
import org.joda.time.format.ISODateTimeFormat;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link Spec11ThreatMatch}. */
@DualDatabaseTest
public class Spec11ThreatMatchTest extends EntityTestCase {
private static final String REGISTRAR_ID = "registrar";
@ -100,8 +103,9 @@ public class Spec11ThreatMatchTest extends EntityTestCase {
.build();
}
@Test
@TestSqlOnly
void testPersistence() {
createTld("tld");
saveRegistrar(REGISTRAR_ID);
jpaTm()
@ -121,7 +125,7 @@ public class Spec11ThreatMatchTest extends EntityTestCase {
assertThat(threat).isEqualTo(persistedThreat);
}
@Test
@TestSqlOnly
@Disabled("We can't rely on foreign keys until we've migrated to SQL")
void testThreatForeignKeyConstraints() {
assertThrowForeignKeyViolation(
@ -152,7 +156,7 @@ public class Spec11ThreatMatchTest extends EntityTestCase {
});
}
@Test
@TestOfyAndSql
void testFailure_threatsWithInvalidFields() {
assertThrows(
IllegalArgumentException.class, () -> threat.asBuilder().setRegistrarId(null).build());

View file

@ -210,77 +210,77 @@ digraph {
78 -> 79 [style=solid label=""]
}
subgraph cluster_80 {
label = "Write to sql: Transforms:Registrar"
label = "Write to sql: Transforms:Registry"
subgraph cluster_81 {
label = "Write to sql: Transforms:Registrar/Shard data for Transforms:Registrar"
label = "Write to sql: Transforms:Registry/Shard data for Transforms:Registry"
subgraph cluster_82 {
label = "Write to sql: Transforms:Registrar/Shard data for Transforms:Registrar/Map"
label = "Write to sql: Transforms:Registry/Shard data for Transforms:Registry/Map"
83 [label="ParMultiDo(Anonymous)"]
79 -> 83 [style=solid label=""]
}
}
subgraph cluster_84 {
label = "Write to sql: Transforms:Registrar/Batch output by shard Transforms:Registrar"
label = "Write to sql: Transforms:Registry/Batch output by shard Transforms:Registry"
subgraph cluster_85 {
label = "Write to sql: Transforms:Registrar/Batch output by shard Transforms:Registrar/ParDo(GroupIntoBatches)"
label = "Write to sql: Transforms:Registry/Batch output by shard Transforms:Registry/ParDo(GroupIntoBatches)"
86 [label="ParMultiDo(GroupIntoBatches)"]
83 -> 86 [style=solid label=""]
}
}
subgraph cluster_87 {
label = "Write to sql: Transforms:Registrar/Write in batch for Transforms:Registrar"
label = "Write to sql: Transforms:Registry/Write in batch for Transforms:Registry"
88 [label="ParMultiDo(SqlBatchWriter)"]
86 -> 88 [style=solid label=""]
}
}
subgraph cluster_89 {
label = "Wait on Transforms:Registrar"
label = "Wait on Transforms:Registry"
subgraph cluster_90 {
label = "Wait on Transforms:Registrar/To wait view 0"
label = "Wait on Transforms:Registry/To wait view 0"
subgraph cluster_91 {
label = "Wait on Transforms:Registrar/To wait view 0/Window.Into()"
label = "Wait on Transforms:Registry/To wait view 0/Window.Into()"
92 [label="Flatten.PCollections"]
88 -> 92 [style=solid label=""]
}
subgraph cluster_93 {
label = "Wait on Transforms:Registrar/To wait view 0/ParDo(CollectWindows)"
label = "Wait on Transforms:Registry/To wait view 0/ParDo(CollectWindows)"
94 [label="ParMultiDo(CollectWindows)"]
92 -> 94 [style=solid label=""]
}
subgraph cluster_95 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any"
subgraph cluster_96 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)"
subgraph cluster_97 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys"
subgraph cluster_98 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys"
subgraph cluster_99 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys/Map"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys/Map"
100 [label="ParMultiDo(Anonymous)"]
94 -> 100 [style=solid label=""]
}
}
}
subgraph cluster_101 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)"
102 [label="GroupByKey"]
100 -> 102 [style=solid label=""]
subgraph cluster_103 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues"
subgraph cluster_104 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues/ParDo(Anonymous)"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues/ParDo(Anonymous)"
105 [label="ParMultiDo(Anonymous)"]
102 -> 105 [style=solid label=""]
}
}
}
subgraph cluster_106 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values"
subgraph cluster_107 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values"
subgraph cluster_108 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values/Map"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values/Map"
109 [label="ParMultiDo(Anonymous)"]
105 -> 109 [style=solid label=""]
}
@ -288,11 +288,11 @@ digraph {
}
}
subgraph cluster_110 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Flatten.Iterables"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Flatten.Iterables"
subgraph cluster_111 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables"
subgraph cluster_112 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables/FlatMap"
label = "Wait on Transforms:Registry/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables/FlatMap"
113 [label="ParMultiDo(Anonymous)"]
109 -> 113 [style=solid label=""]
}
@ -300,11 +300,11 @@ digraph {
}
}
subgraph cluster_114 {
label = "Wait on Transforms:Registrar/To wait view 0/View.AsList"
label = "Wait on Transforms:Registry/To wait view 0/View.AsList"
subgraph cluster_115 {
label = "Wait on Transforms:Registrar/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization"
label = "Wait on Transforms:Registry/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization"
subgraph cluster_116 {
label = "Wait on Transforms:Registrar/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization/ParDo(VoidKeyToMultimapMaterialization)"
label = "Wait on Transforms:Registry/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization/ParDo(VoidKeyToMultimapMaterialization)"
117 [label="ParMultiDo(VoidKeyToMultimapMaterialization)"]
113 -> 117 [style=solid label=""]
}
@ -314,9 +314,9 @@ digraph {
}
}
subgraph cluster_119 {
label = "Wait on Transforms:Registrar/Wait"
label = "Wait on Transforms:Registry/Wait"
subgraph cluster_120 {
label = "Wait on Transforms:Registrar/Wait/Map"
label = "Wait on Transforms:Registry/Wait/Map"
121 [label="ParMultiDo(Anonymous)"]
79 -> 121 [style=solid label=""]
117 -> 121 [style=dashed label=""]
@ -324,196 +324,196 @@ digraph {
}
}
subgraph cluster_122 {
label = "Write to sql: Transforms:ContactResource"
label = "Write to sql: Transforms:Registrar"
subgraph cluster_123 {
label = "Write to sql: Transforms:ContactResource/Shard data for Transforms:ContactResource"
label = "Write to sql: Transforms:Registrar/Shard data for Transforms:Registrar"
subgraph cluster_124 {
label = "Write to sql: Transforms:ContactResource/Shard data for Transforms:ContactResource/Map"
label = "Write to sql: Transforms:Registrar/Shard data for Transforms:Registrar/Map"
125 [label="ParMultiDo(Anonymous)"]
121 -> 125 [style=solid label=""]
}
}
subgraph cluster_126 {
label = "Write to sql: Transforms:ContactResource/Batch output by shard Transforms:ContactResource"
label = "Write to sql: Transforms:Registrar/Batch output by shard Transforms:Registrar"
subgraph cluster_127 {
label = "Write to sql: Transforms:ContactResource/Batch output by shard Transforms:ContactResource/ParDo(GroupIntoBatches)"
label = "Write to sql: Transforms:Registrar/Batch output by shard Transforms:Registrar/ParDo(GroupIntoBatches)"
128 [label="ParMultiDo(GroupIntoBatches)"]
125 -> 128 [style=solid label=""]
}
}
subgraph cluster_129 {
label = "Write to sql: Transforms:ContactResource/Write in batch for Transforms:ContactResource"
label = "Write to sql: Transforms:Registrar/Write in batch for Transforms:Registrar"
130 [label="ParMultiDo(SqlBatchWriter)"]
128 -> 130 [style=solid label=""]
}
}
subgraph cluster_131 {
label = "Remove circular foreign keys from DomainBase"
132 [label="ParMultiDo(RemoveDomainBaseForeignKeys)"]
79 -> 132 [style=solid label=""]
}
subgraph cluster_133 {
label = "Wait on phase one"
subgraph cluster_134 {
label = "Wait on phase one/To wait view 0"
label = "Wait on Transforms:Registrar"
subgraph cluster_132 {
label = "Wait on Transforms:Registrar/To wait view 0"
subgraph cluster_133 {
label = "Wait on Transforms:Registrar/To wait view 0/Window.Into()"
134 [label="Flatten.PCollections"]
130 -> 134 [style=solid label=""]
}
subgraph cluster_135 {
label = "Wait on phase one/To wait view 0/Window.Into()"
136 [label="Flatten.PCollections"]
130 -> 136 [style=solid label=""]
label = "Wait on Transforms:Registrar/To wait view 0/ParDo(CollectWindows)"
136 [label="ParMultiDo(CollectWindows)"]
134 -> 136 [style=solid label=""]
}
subgraph cluster_137 {
label = "Wait on phase one/To wait view 0/ParDo(CollectWindows)"
138 [label="ParMultiDo(CollectWindows)"]
136 -> 138 [style=solid label=""]
}
subgraph cluster_139 {
label = "Wait on phase one/To wait view 0/Sample.Any"
subgraph cluster_140 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)"
subgraph cluster_141 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys"
subgraph cluster_142 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys"
subgraph cluster_143 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys/Map"
144 [label="ParMultiDo(Anonymous)"]
138 -> 144 [style=solid label=""]
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any"
subgraph cluster_138 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)"
subgraph cluster_139 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys"
subgraph cluster_140 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys"
subgraph cluster_141 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys/Map"
142 [label="ParMultiDo(Anonymous)"]
136 -> 142 [style=solid label=""]
}
}
}
subgraph cluster_145 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)"
146 [label="GroupByKey"]
144 -> 146 [style=solid label=""]
subgraph cluster_147 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues"
subgraph cluster_148 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues/ParDo(Anonymous)"
149 [label="ParMultiDo(Anonymous)"]
146 -> 149 [style=solid label=""]
subgraph cluster_143 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)"
144 [label="GroupByKey"]
142 -> 144 [style=solid label=""]
subgraph cluster_145 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues"
subgraph cluster_146 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues/ParDo(Anonymous)"
147 [label="ParMultiDo(Anonymous)"]
144 -> 147 [style=solid label=""]
}
}
}
subgraph cluster_150 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values"
subgraph cluster_151 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values"
subgraph cluster_152 {
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values/Map"
153 [label="ParMultiDo(Anonymous)"]
149 -> 153 [style=solid label=""]
subgraph cluster_148 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values"
subgraph cluster_149 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values"
subgraph cluster_150 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values/Map"
151 [label="ParMultiDo(Anonymous)"]
147 -> 151 [style=solid label=""]
}
}
}
}
subgraph cluster_154 {
label = "Wait on phase one/To wait view 0/Sample.Any/Flatten.Iterables"
subgraph cluster_155 {
label = "Wait on phase one/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables"
subgraph cluster_156 {
label = "Wait on phase one/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables/FlatMap"
157 [label="ParMultiDo(Anonymous)"]
153 -> 157 [style=solid label=""]
subgraph cluster_152 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Flatten.Iterables"
subgraph cluster_153 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables"
subgraph cluster_154 {
label = "Wait on Transforms:Registrar/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables/FlatMap"
155 [label="ParMultiDo(Anonymous)"]
151 -> 155 [style=solid label=""]
}
}
}
}
subgraph cluster_158 {
label = "Wait on phase one/To wait view 0/View.AsList"
subgraph cluster_159 {
label = "Wait on phase one/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization"
subgraph cluster_160 {
label = "Wait on phase one/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization/ParDo(VoidKeyToMultimapMaterialization)"
161 [label="ParMultiDo(VoidKeyToMultimapMaterialization)"]
157 -> 161 [style=solid label=""]
subgraph cluster_156 {
label = "Wait on Transforms:Registrar/To wait view 0/View.AsList"
subgraph cluster_157 {
label = "Wait on Transforms:Registrar/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization"
subgraph cluster_158 {
label = "Wait on Transforms:Registrar/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization/ParDo(VoidKeyToMultimapMaterialization)"
159 [label="ParMultiDo(VoidKeyToMultimapMaterialization)"]
155 -> 159 [style=solid label=""]
}
}
162 [label="View.CreatePCollectionView"]
161 -> 162 [style=solid label=""]
160 [label="View.CreatePCollectionView"]
159 -> 160 [style=solid label=""]
}
}
subgraph cluster_163 {
label = "Wait on phase one/Wait"
subgraph cluster_164 {
label = "Wait on phase one/Wait/Map"
165 [label="ParMultiDo(Anonymous)"]
132 -> 165 [style=solid label=""]
161 -> 165 [style=dashed label=""]
subgraph cluster_161 {
label = "Wait on Transforms:Registrar/Wait"
subgraph cluster_162 {
label = "Wait on Transforms:Registrar/Wait/Map"
163 [label="ParMultiDo(Anonymous)"]
79 -> 163 [style=solid label=""]
159 -> 163 [style=dashed label=""]
}
}
}
subgraph cluster_166 {
label = "Write to sql: DomainBase without circular foreign keys"
subgraph cluster_167 {
label = "Write to sql: DomainBase without circular foreign keys/Shard data for DomainBase without circular foreign keys"
subgraph cluster_168 {
label = "Write to sql: DomainBase without circular foreign keys/Shard data for DomainBase without circular foreign keys/Map"
169 [label="ParMultiDo(Anonymous)"]
165 -> 169 [style=solid label=""]
subgraph cluster_164 {
label = "Write to sql: Transforms:ContactResource"
subgraph cluster_165 {
label = "Write to sql: Transforms:ContactResource/Shard data for Transforms:ContactResource"
subgraph cluster_166 {
label = "Write to sql: Transforms:ContactResource/Shard data for Transforms:ContactResource/Map"
167 [label="ParMultiDo(Anonymous)"]
163 -> 167 [style=solid label=""]
}
}
subgraph cluster_170 {
label = "Write to sql: DomainBase without circular foreign keys/Batch output by shard DomainBase without circular foreign keys"
subgraph cluster_171 {
label = "Write to sql: DomainBase without circular foreign keys/Batch output by shard DomainBase without circular foreign keys/ParDo(GroupIntoBatches)"
172 [label="ParMultiDo(GroupIntoBatches)"]
169 -> 172 [style=solid label=""]
subgraph cluster_168 {
label = "Write to sql: Transforms:ContactResource/Batch output by shard Transforms:ContactResource"
subgraph cluster_169 {
label = "Write to sql: Transforms:ContactResource/Batch output by shard Transforms:ContactResource/ParDo(GroupIntoBatches)"
170 [label="ParMultiDo(GroupIntoBatches)"]
167 -> 170 [style=solid label=""]
}
}
subgraph cluster_173 {
label = "Write to sql: DomainBase without circular foreign keys/Write in batch for DomainBase without circular foreign keys"
174 [label="ParMultiDo(SqlBatchWriter)"]
172 -> 174 [style=solid label=""]
subgraph cluster_171 {
label = "Write to sql: Transforms:ContactResource/Write in batch for Transforms:ContactResource"
172 [label="ParMultiDo(SqlBatchWriter)"]
170 -> 172 [style=solid label=""]
}
}
subgraph cluster_173 {
label = "Remove circular foreign keys from DomainBase"
174 [label="ParMultiDo(RemoveDomainBaseForeignKeys)"]
79 -> 174 [style=solid label=""]
}
subgraph cluster_175 {
label = "Wait on DomainBaseNoFkeys"
label = "Wait on phase one"
subgraph cluster_176 {
label = "Wait on DomainBaseNoFkeys/To wait view 0"
label = "Wait on phase one/To wait view 0"
subgraph cluster_177 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Window.Into()"
label = "Wait on phase one/To wait view 0/Window.Into()"
178 [label="Flatten.PCollections"]
174 -> 178 [style=solid label=""]
172 -> 178 [style=solid label=""]
}
subgraph cluster_179 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/ParDo(CollectWindows)"
label = "Wait on phase one/To wait view 0/ParDo(CollectWindows)"
180 [label="ParMultiDo(CollectWindows)"]
178 -> 180 [style=solid label=""]
}
subgraph cluster_181 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any"
label = "Wait on phase one/To wait view 0/Sample.Any"
subgraph cluster_182 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)"
subgraph cluster_183 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys"
subgraph cluster_184 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys"
subgraph cluster_185 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys/Map"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys/Map"
186 [label="ParMultiDo(Anonymous)"]
180 -> 186 [style=solid label=""]
}
}
}
subgraph cluster_187 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)"
188 [label="GroupByKey"]
186 -> 188 [style=solid label=""]
subgraph cluster_189 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues"
subgraph cluster_190 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues/ParDo(Anonymous)"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues/ParDo(Anonymous)"
191 [label="ParMultiDo(Anonymous)"]
188 -> 191 [style=solid label=""]
}
}
}
subgraph cluster_192 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values"
subgraph cluster_193 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values"
subgraph cluster_194 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values/Map"
label = "Wait on phase one/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values/Map"
195 [label="ParMultiDo(Anonymous)"]
191 -> 195 [style=solid label=""]
}
@ -521,11 +521,11 @@ digraph {
}
}
subgraph cluster_196 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Flatten.Iterables"
label = "Wait on phase one/To wait view 0/Sample.Any/Flatten.Iterables"
subgraph cluster_197 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables"
label = "Wait on phase one/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables"
subgraph cluster_198 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables/FlatMap"
label = "Wait on phase one/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables/FlatMap"
199 [label="ParMultiDo(Anonymous)"]
195 -> 199 [style=solid label=""]
}
@ -533,11 +533,11 @@ digraph {
}
}
subgraph cluster_200 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/View.AsList"
label = "Wait on phase one/To wait view 0/View.AsList"
subgraph cluster_201 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization"
label = "Wait on phase one/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization"
subgraph cluster_202 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization/ParDo(VoidKeyToMultimapMaterialization)"
label = "Wait on phase one/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization/ParDo(VoidKeyToMultimapMaterialization)"
203 [label="ParMultiDo(VoidKeyToMultimapMaterialization)"]
199 -> 203 [style=solid label=""]
}
@ -547,38 +547,152 @@ digraph {
}
}
subgraph cluster_205 {
label = "Wait on DomainBaseNoFkeys/Wait"
label = "Wait on phase one/Wait"
subgraph cluster_206 {
label = "Wait on DomainBaseNoFkeys/Wait/Map"
label = "Wait on phase one/Wait/Map"
207 [label="ParMultiDo(Anonymous)"]
79 -> 207 [style=solid label=""]
174 -> 207 [style=solid label=""]
203 -> 207 [style=dashed label=""]
}
}
}
subgraph cluster_208 {
label = "Write to sql: Transforms:HostResource"
label = "Write to sql: DomainBase without circular foreign keys"
subgraph cluster_209 {
label = "Write to sql: Transforms:HostResource/Shard data for Transforms:HostResource"
label = "Write to sql: DomainBase without circular foreign keys/Shard data for DomainBase without circular foreign keys"
subgraph cluster_210 {
label = "Write to sql: Transforms:HostResource/Shard data for Transforms:HostResource/Map"
label = "Write to sql: DomainBase without circular foreign keys/Shard data for DomainBase without circular foreign keys/Map"
211 [label="ParMultiDo(Anonymous)"]
207 -> 211 [style=solid label=""]
}
}
subgraph cluster_212 {
label = "Write to sql: Transforms:HostResource/Batch output by shard Transforms:HostResource"
label = "Write to sql: DomainBase without circular foreign keys/Batch output by shard DomainBase without circular foreign keys"
subgraph cluster_213 {
label = "Write to sql: Transforms:HostResource/Batch output by shard Transforms:HostResource/ParDo(GroupIntoBatches)"
label = "Write to sql: DomainBase without circular foreign keys/Batch output by shard DomainBase without circular foreign keys/ParDo(GroupIntoBatches)"
214 [label="ParMultiDo(GroupIntoBatches)"]
211 -> 214 [style=solid label=""]
}
}
subgraph cluster_215 {
label = "Write to sql: Transforms:HostResource/Write in batch for Transforms:HostResource"
label = "Write to sql: DomainBase without circular foreign keys/Write in batch for DomainBase without circular foreign keys"
216 [label="ParMultiDo(SqlBatchWriter)"]
214 -> 216 [style=solid label=""]
}
}
subgraph cluster_217 {
label = "Wait on DomainBaseNoFkeys"
subgraph cluster_218 {
label = "Wait on DomainBaseNoFkeys/To wait view 0"
subgraph cluster_219 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Window.Into()"
220 [label="Flatten.PCollections"]
216 -> 220 [style=solid label=""]
}
subgraph cluster_221 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/ParDo(CollectWindows)"
222 [label="ParMultiDo(CollectWindows)"]
220 -> 222 [style=solid label=""]
}
subgraph cluster_223 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any"
subgraph cluster_224 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)"
subgraph cluster_225 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys"
subgraph cluster_226 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys"
subgraph cluster_227 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/WithKeys/AddKeys/Map"
228 [label="ParMultiDo(Anonymous)"]
222 -> 228 [style=solid label=""]
}
}
}
subgraph cluster_229 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)"
230 [label="GroupByKey"]
228 -> 230 [style=solid label=""]
subgraph cluster_231 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues"
subgraph cluster_232 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Combine.perKey(SampleAny)/Combine.GroupedValues/ParDo(Anonymous)"
233 [label="ParMultiDo(Anonymous)"]
230 -> 233 [style=solid label=""]
}
}
}
subgraph cluster_234 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values"
subgraph cluster_235 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values"
subgraph cluster_236 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Combine.globally(SampleAny)/Values/Values/Map"
237 [label="ParMultiDo(Anonymous)"]
233 -> 237 [style=solid label=""]
}
}
}
}
subgraph cluster_238 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Flatten.Iterables"
subgraph cluster_239 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables"
subgraph cluster_240 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/Sample.Any/Flatten.Iterables/FlattenIterables/FlatMap"
241 [label="ParMultiDo(Anonymous)"]
237 -> 241 [style=solid label=""]
}
}
}
}
subgraph cluster_242 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/View.AsList"
subgraph cluster_243 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization"
subgraph cluster_244 {
label = "Wait on DomainBaseNoFkeys/To wait view 0/View.AsList/View.VoidKeyToMultimapMaterialization/ParDo(VoidKeyToMultimapMaterialization)"
245 [label="ParMultiDo(VoidKeyToMultimapMaterialization)"]
241 -> 245 [style=solid label=""]
}
}
246 [label="View.CreatePCollectionView"]
245 -> 246 [style=solid label=""]
}
}
subgraph cluster_247 {
label = "Wait on DomainBaseNoFkeys/Wait"
subgraph cluster_248 {
label = "Wait on DomainBaseNoFkeys/Wait/Map"
249 [label="ParMultiDo(Anonymous)"]
79 -> 249 [style=solid label=""]
245 -> 249 [style=dashed label=""]
}
}
}
subgraph cluster_250 {
label = "Write to sql: Transforms:HostResource"
subgraph cluster_251 {
label = "Write to sql: Transforms:HostResource/Shard data for Transforms:HostResource"
subgraph cluster_252 {
label = "Write to sql: Transforms:HostResource/Shard data for Transforms:HostResource/Map"
253 [label="ParMultiDo(Anonymous)"]
249 -> 253 [style=solid label=""]
}
}
subgraph cluster_254 {
label = "Write to sql: Transforms:HostResource/Batch output by shard Transforms:HostResource"
subgraph cluster_255 {
label = "Write to sql: Transforms:HostResource/Batch output by shard Transforms:HostResource/ParDo(GroupIntoBatches)"
256 [label="ParMultiDo(GroupIntoBatches)"]
253 -> 256 [style=solid label=""]
}
}
subgraph cluster_257 {
label = "Write to sql: Transforms:HostResource/Write in batch for Transforms:HostResource"
258 [label="ParMultiDo(SqlBatchWriter)"]
256 -> 258 [style=solid label=""]
}
}
}
}