From 19bd7d272a9527f7a61e2a4b874dfe4d5753a250 Mon Sep 17 00:00:00 2001 From: Shrikant Sharat Kandula Date: Fri, 18 Sep 2020 06:38:53 +0530 Subject: [PATCH] Use a unique instance ID for pinging home (#566) * Use a unique instance ID for pinging home * Fix event name --- .../com/appsmith/server/domains/Config.java | 2 ++ .../server/migrations/DatabaseChangelog.java | 8 +++++ .../server/solutions/PingScheduledTask.java | 32 ++++++++++++++----- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Config.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Config.java index 462913f317..1518a42e01 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Config.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/domains/Config.java @@ -1,6 +1,7 @@ package com.appsmith.server.domains; import com.appsmith.external.models.BaseDomain; +import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -12,6 +13,7 @@ import org.springframework.data.mongodb.core.mapping.Document; @Setter @ToString @NoArgsConstructor +@AllArgsConstructor @Document public class Config extends BaseDomain { JSONObject config; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog.java index 3b4defea3c..c8ec14eb7e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/migrations/DatabaseChangelog.java @@ -916,4 +916,12 @@ public class DatabaseChangelog { } } + @ChangeSet(order = "025", id = "generate-unique-id-for-instance", author = "") + public void generateUniqueIdForInstance(MongoTemplate mongoTemplate) { + mongoTemplate.insert(new Config( + new JSONObject(Map.of("value", new ObjectId().toHexString())), + "instance-id" + )); + } + } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/PingScheduledTask.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/PingScheduledTask.java index 92ec42882a..49da888864 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/PingScheduledTask.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/PingScheduledTask.java @@ -1,5 +1,7 @@ package com.appsmith.server.solutions; +import com.appsmith.server.services.ConfigService; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.http.MediaType; @@ -19,28 +21,38 @@ import java.util.Map; @Component @ConditionalOnProperty(prefix = "is", name = "self-hosted") @Slf4j +@RequiredArgsConstructor public class PingScheduledTask { + private final ConfigService configService; + public static final URI GET_IP_URI = URI.create("https://api6.ipify.org"); /** * Gets the external IP address of this server and pings a data point to indicate that this server instance is live. + * We use an initial delay of two minutes to roughly wait for the application along with the migrations are finished + * and ready. */ // Number of milliseconds between the start of each scheduled calls to this method. - @Scheduled(fixedRate = 6 * 60 * 60 * 1000 /* six hours */) + @Scheduled(initialDelay = 2 * 60 * 1000 /* two minutes */, fixedRate = 6 * 60 * 60 * 1000 /* six hours */) public void pingSchedule() { - getInstallationId() - .flatMap(this::doPing) - .doOnError(error -> log.debug("Error pinging home", error)) + Mono.zip(getInstanceId(), getAddress()) + .flatMap(tuple -> doPing(tuple.getT1(), tuple.getT2())) .subscribeOn(Schedulers.single()) .subscribe(); } + private Mono getInstanceId() { + return configService.getByName("instance-id") + .map(config -> config.getConfig().getAsString("value")); + } + /** * This method hits an API endpoint that returns the external IP address of this server instance. + * * @return A publisher that yields the IP address. */ - private Mono getInstallationId() { + private Mono getAddress() { return WebClient .create() .get() @@ -52,10 +64,12 @@ public class PingScheduledTask { /** * Given a unique ID (called a `userId` here), this method hits the Segment API to save a data point on this server * instance being live. - * @param userId A unique identifier for this server instance (usually, the external IP address of the server). + * + * @param instanceId A unique identifier for this server instance, usually generated at the server's first start. + * @param ipAddress The external IP address of this instance's machine. * @return A publisher that yields the string response of recording the data point. */ - private Mono doPing(String userId) { + private Mono doPing(String instanceId, String ipAddress) { // Note: Hard-coding Segment auth header and the event name intentionally. These are not intended to be // environment specific values, instead, they are common values for all self-hosted environments. As such, they // are not intended to be configurable. @@ -66,7 +80,9 @@ public class PingScheduledTask { .header("Authorization", "Basic QjJaM3hXRThXdDRwYnZOWDRORnJPNWZ3VXdnYWtFbk06") .contentType(MediaType.APPLICATION_JSON) .body(BodyInserters.fromValue(Map.of( - "userId", userId, + "userId", instanceId, + "context", Map.of("ip", ipAddress), + "properties", Map.of("ip", ipAddress), "event", "Instance Active" ))) .retrieve()