Use sequences for numbering new datasources.
This commit is contained in:
parent
b13a7a5df3
commit
7037d99cfa
|
|
@ -20,6 +20,10 @@ import java.util.Set;
|
|||
@NoArgsConstructor
|
||||
@Document
|
||||
public class Datasource extends BaseDomain {
|
||||
|
||||
@Transient
|
||||
public static final String DEFAULT_NAME_PREFIX = "Untitled Datasource";
|
||||
|
||||
String name;
|
||||
|
||||
String pluginId;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
package com.appsmith.server.domains;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public class Sequence {
|
||||
|
||||
private String name;
|
||||
|
||||
@Getter
|
||||
private Long nextNumber;
|
||||
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ import com.appsmith.server.domains.Plugin;
|
|||
import com.appsmith.server.domains.PluginType;
|
||||
import com.appsmith.server.domains.Query;
|
||||
import com.appsmith.server.domains.Role;
|
||||
import com.appsmith.server.domains.Sequence;
|
||||
import com.appsmith.server.domains.Setting;
|
||||
import com.appsmith.server.domains.User;
|
||||
import com.appsmith.server.dtos.OrganizationPluginStatus;
|
||||
|
|
@ -31,7 +32,6 @@ import org.springframework.data.mongodb.core.MongoTemplate;
|
|||
import org.springframework.data.mongodb.core.index.CompoundIndexDefinition;
|
||||
import org.springframework.data.mongodb.core.index.Index;
|
||||
import org.springframework.data.mongodb.core.index.IndexOperations;
|
||||
import org.springframework.data.mongodb.core.query.Criteria;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.time.Instant;
|
||||
|
|
@ -42,6 +42,10 @@ import java.util.Set;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.where;
|
||||
import static org.springframework.data.mongodb.core.query.Query.query;
|
||||
import static org.springframework.data.mongodb.core.query.Update.update;
|
||||
|
||||
@Slf4j
|
||||
@ChangeLog(order = "001")
|
||||
public class DatabaseChangelog {
|
||||
|
|
@ -263,7 +267,7 @@ public class DatabaseChangelog {
|
|||
@ChangeSet(order = "006", id = "hide-rapidapi-plugin", author = "")
|
||||
public void hideRapidApiPluginFromCreateDatasource(MongoTemplate mongoTemplate) {
|
||||
final Plugin rapidApiPlugin = mongoTemplate.findOne(
|
||||
org.springframework.data.mongodb.core.query.Query.query(Criteria.where("packageName").is("rapidapi-plugin")),
|
||||
query(where("packageName").is("rapidapi-plugin")),
|
||||
Plugin.class
|
||||
);
|
||||
|
||||
|
|
@ -341,7 +345,7 @@ public class DatabaseChangelog {
|
|||
@ChangeSet(order = "011", id = "install-default-plugins-to-all-organizations", author = "")
|
||||
public void installDefaultPluginsToAllOrganizations(MongoTemplate mongoTemplate) {
|
||||
final List<Plugin> defaultPlugins = mongoTemplate.find(
|
||||
org.springframework.data.mongodb.core.query.Query.query(Criteria.where("defaultInstall").is(true)),
|
||||
query(where("defaultInstall").is(true)),
|
||||
Plugin.class
|
||||
);
|
||||
|
||||
|
|
@ -369,7 +373,7 @@ public class DatabaseChangelog {
|
|||
@ChangeSet(order = "012", id = "ensure-datasource-created-and-updated-at-fields", author = "")
|
||||
public void ensureDatasourceCreatedAndUpdatedAt(MongoTemplate mongoTemplate) {
|
||||
final List<Datasource> missingCreatedAt = mongoTemplate.find(
|
||||
org.springframework.data.mongodb.core.query.Query.query(Criteria.where("createdAt").exists(false)),
|
||||
query(where("createdAt").exists(false)),
|
||||
Datasource.class
|
||||
);
|
||||
|
||||
|
|
@ -379,7 +383,7 @@ public class DatabaseChangelog {
|
|||
}
|
||||
|
||||
final List<Datasource> missingUpdatedAt = mongoTemplate.find(
|
||||
org.springframework.data.mongodb.core.query.Query.query(Criteria.where("updatedAt").exists(false)),
|
||||
query(where("updatedAt").exists(false)),
|
||||
Datasource.class
|
||||
);
|
||||
|
||||
|
|
@ -389,4 +393,29 @@ public class DatabaseChangelog {
|
|||
}
|
||||
}
|
||||
|
||||
@ChangeSet(order = "013", id = "add-index-for-sequence-name", author = "")
|
||||
public void addIndexForSequenceName(MongoTemplate mongoTemplate) {
|
||||
ensureIndexes(mongoTemplate, Sequence.class,
|
||||
makeIndex(FieldName.NAME).unique()
|
||||
);
|
||||
}
|
||||
|
||||
@ChangeSet(order = "014", id = "set-initial-sequence-for-datasource", author = "")
|
||||
public void setInitialSequenceForDatasource(MongoTemplate mongoTemplate) {
|
||||
final Long maxUntitledDatasourceNumber = mongoTemplate.find(
|
||||
query(where(FieldName.NAME).regex("^" + Datasource.DEFAULT_NAME_PREFIX + " \\d+$")),
|
||||
Datasource.class
|
||||
)
|
||||
.stream()
|
||||
.map(datasource -> Long.parseLong(datasource.getName().split(" ")[2]))
|
||||
.max(Long::compareTo)
|
||||
.orElse(0L);
|
||||
|
||||
mongoTemplate.upsert(
|
||||
query(where(FieldName.NAME).is(mongoTemplate.getCollectionName(Datasource.class))),
|
||||
update("nextNumber", maxUntitledDatasourceNumber + 1),
|
||||
Sequence.class
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package com.appsmith.server.repositories;
|
||||
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.domains.Datasource;
|
||||
import org.springframework.data.mongodb.repository.Query;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
|
@ -15,6 +13,4 @@ public interface DatasourceRepository extends BaseRepository<Datasource, String>
|
|||
|
||||
Flux<Datasource> findAllByOrganizationId(String organizationId);
|
||||
|
||||
@Query(value = "{" + FieldName.NAME + ": {$regex: ?0}}", count = true)
|
||||
Mono<Long> countNamesByPrefix(String namePrefix);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ public interface DatasourceService extends CrudService<Datasource, String> {
|
|||
|
||||
Set<String> extractKeysFromDatasource(Datasource datasource);
|
||||
|
||||
Mono<String> getNextUniqueName(String initialSlug);
|
||||
|
||||
Mono<Datasource> validateDatasource(Datasource datasource);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ public class DatasourceServiceImpl extends BaseService<DatasourceRepository, Dat
|
|||
private final ObjectMapper objectMapper;
|
||||
private final PluginService pluginService;
|
||||
private final PluginExecutorHelper pluginExecutorHelper;
|
||||
private final SequenceService sequenceService;
|
||||
|
||||
@Autowired
|
||||
public DatasourceServiceImpl(Scheduler scheduler,
|
||||
|
|
@ -54,7 +55,8 @@ public class DatasourceServiceImpl extends BaseService<DatasourceRepository, Dat
|
|||
SessionUserService sessionUserService,
|
||||
ObjectMapper objectMapper,
|
||||
PluginService pluginService,
|
||||
PluginExecutorHelper pluginExecutorHelper) {
|
||||
PluginExecutorHelper pluginExecutorHelper,
|
||||
SequenceService sequenceService) {
|
||||
super(scheduler, validator, mongoConverter, reactiveMongoTemplate, repository, analyticsService);
|
||||
this.repository = repository;
|
||||
this.organizationService = organizationService;
|
||||
|
|
@ -62,6 +64,7 @@ public class DatasourceServiceImpl extends BaseService<DatasourceRepository, Dat
|
|||
this.objectMapper = objectMapper;
|
||||
this.pluginService = pluginService;
|
||||
this.pluginExecutorHelper = pluginExecutorHelper;
|
||||
this.sequenceService = sequenceService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -73,21 +76,16 @@ public class DatasourceServiceImpl extends BaseService<DatasourceRepository, Dat
|
|||
Mono<Datasource> datasourceMono = Mono.just(datasource);
|
||||
|
||||
if (StringUtils.isEmpty(datasource.getName())) {
|
||||
datasourceMono = datasourceMono.zipWith(
|
||||
getNextUniqueName("Untitled datasource"),
|
||||
(datasource1, name) -> {
|
||||
datasource1.setName(name);
|
||||
datasourceMono = sequenceService
|
||||
.getNextAsSuffix(Datasource.class)
|
||||
.zipWith(datasourceMono, (sequenceNumber, datasource1) -> {
|
||||
datasource1.setName(Datasource.DEFAULT_NAME_PREFIX + sequenceNumber);
|
||||
return datasource1;
|
||||
});
|
||||
}
|
||||
|
||||
return datasourceMono.flatMap(this::validateAndSaveDatasourceToRepository);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<String> getNextUniqueName(String namePrefix) {
|
||||
return repository.countNamesByPrefix(namePrefix)
|
||||
.map(max -> namePrefix + (max == 0 ? "" : " " + (max + 1)));
|
||||
return datasourceMono
|
||||
.flatMap(this::validateAndSaveDatasourceToRepository);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package com.appsmith.server.services;
|
||||
|
||||
import com.appsmith.external.models.BaseDomain;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public interface SequenceService {
|
||||
|
||||
Mono<Long> getNext(String name);
|
||||
|
||||
Mono<Long> getNext(Class<? extends BaseDomain> domainClass);
|
||||
|
||||
Mono<String> getNextAsSuffix(Class<? extends BaseDomain> domainClass);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
package com.appsmith.server.services;
|
||||
|
||||
import com.appsmith.external.models.BaseDomain;
|
||||
import com.appsmith.server.domains.Sequence;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.mongodb.core.ReactiveMongoTemplate;
|
||||
import org.springframework.data.mongodb.core.query.Update;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import static org.springframework.data.mongodb.core.FindAndModifyOptions.options;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.where;
|
||||
import static org.springframework.data.mongodb.core.query.Query.query;
|
||||
|
||||
@Service
|
||||
public class SequenceServiceImpl implements SequenceService {
|
||||
|
||||
private final ReactiveMongoTemplate mongoTemplate;
|
||||
|
||||
@Autowired
|
||||
public SequenceServiceImpl(ReactiveMongoTemplate mongoTemplate) {
|
||||
this.mongoTemplate = mongoTemplate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Long> getNext(String name) {
|
||||
return mongoTemplate
|
||||
.findAndModify(
|
||||
query(where("name").is(name)),
|
||||
new Update().inc("nextNumber", 1),
|
||||
options().upsert(true),
|
||||
Sequence.class
|
||||
)
|
||||
.map(Sequence::getNextNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Long> getNext(Class<? extends BaseDomain> domainClass) {
|
||||
return getNext(mongoTemplate.getCollectionName(domainClass));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<String> getNextAsSuffix(Class<? extends BaseDomain> domainClass) {
|
||||
return getNext(mongoTemplate.getCollectionName(domainClass))
|
||||
.map(number -> number > 1 ? " " + number : "");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -253,12 +253,12 @@ public class DatasourceServiceTest {
|
|||
final Datasource ds1 = tuple2.getT1();
|
||||
assertThat(ds1.getId()).isNotEmpty();
|
||||
assertThat(ds1.getPluginId()).isEqualTo(datasource1.getPluginId());
|
||||
assertThat(ds1.getName()).isEqualTo("Untitled datasource");
|
||||
assertThat(ds1.getName()).isEqualTo("Untitled Datasource");
|
||||
|
||||
final Datasource ds2 = tuple2.getT2();
|
||||
assertThat(ds2.getId()).isNotEmpty();
|
||||
assertThat(ds2.getPluginId()).isEqualTo(datasource1.getPluginId());
|
||||
assertThat(ds2.getName()).isEqualTo("Untitled datasource 2");
|
||||
assertThat(ds2.getName()).isEqualTo("Untitled Datasource 2");
|
||||
})
|
||||
.verifyComplete();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user