Merge pull request #5 from jazzm0/feature/device-service
This commit is contained in:
commit
2caf1a5b38
19 changed files with 805 additions and 0 deletions
4
src/.gitignore
vendored
4
src/.gitignore
vendored
|
@ -3,3 +3,7 @@
|
|||
# run "dep ensure --vendor-only" to download the dependencies to vendor/ based
|
||||
# on the Gopkg.{toml,lock} files in that directory.
|
||||
vendor/
|
||||
tamagotchi-service/target
|
||||
tamagotchi-service/.idea
|
||||
*.iml
|
||||
|
||||
|
|
32
src/tamagotchi-service/.gitignore
vendored
Normal file
32
src/tamagotchi-service/.gitignore
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
.mta
|
||||
.che
|
||||
|
||||
|
||||
/**/node_modules
|
||||
/**/target
|
||||
/**/dist
|
||||
|
||||
/**/.project
|
||||
/**/.settings
|
||||
/**/.classpath
|
||||
/**/.springBeans
|
||||
/**/.factorypath
|
||||
/**/.idea
|
||||
|
||||
// Generated Artifacts
|
||||
/**/edmx/
|
||||
/**/gen
|
||||
/**/src/generated
|
||||
/**/dist
|
||||
/**/webapp/localService/metadata.xml
|
||||
|
||||
|
||||
|
||||
|
||||
// Files and folders generated by WebIDE build and not to be committed
|
||||
/uideployer/resources/
|
||||
/uideployer/deploymentTemp/
|
||||
|
||||
|
||||
/**/package-lock.json
|
||||
/**/*.mtar
|
8
src/tamagotchi-service/app.yaml
Normal file
8
src/tamagotchi-service/app.yaml
Normal file
|
@ -0,0 +1,8 @@
|
|||
runtime: java11
|
||||
entrypoint: java -jar target/tamagotchi-service-0.1.0.jar
|
||||
inbound_services:
|
||||
- warmup
|
||||
automatic_scaling:
|
||||
max_instances: 1
|
||||
min_instances: 1
|
||||
|
76
src/tamagotchi-service/pom.xml
Normal file
76
src/tamagotchi-service/pom.xml
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.sap</groupId>
|
||||
<artifactId>tamagotchi-service</artifactId>
|
||||
<version>0.1.0</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.6.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.cloud</groupId>
|
||||
<artifactId>libraries-bom</artifactId>
|
||||
<version>2.9.0</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.cloud</groupId>
|
||||
<artifactId>google-cloud-pubsub</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.jayway.jsonpath</groupId>
|
||||
<artifactId>json-path</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.google.appengine</groupId>
|
||||
<artifactId>appengine-maven-plugin</artifactId>
|
||||
<version>1.9.77</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,11 @@
|
|||
package com.sap.tamagotchi;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class Application {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(Application.class, args);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.sap.tamagotchi.configuration;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class ApplicationConfiguration {
|
||||
|
||||
@Bean
|
||||
public ObjectMapper objectMapper() {
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
objectMapper.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);
|
||||
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
|
||||
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
|
||||
objectMapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
|
||||
return objectMapper;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.sap.tamagotchi.controller;
|
||||
|
||||
import static com.sap.tamagotchi.model.Color.RED;
|
||||
import static com.sap.tamagotchi.model.Color.YELLOW;
|
||||
import static org.springframework.http.ResponseEntity.ok;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.sap.tamagotchi.model.Color;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import com.sap.tamagotchi.model.CreateDevicePayload;
|
||||
import com.sap.tamagotchi.model.Device;
|
||||
import com.sap.tamagotchi.service.TamagotchiService;
|
||||
|
||||
@RestController
|
||||
public class DeviceController {
|
||||
|
||||
private final TamagotchiService tamagotchiService;
|
||||
|
||||
@Autowired
|
||||
public DeviceController(TamagotchiService tamagotchiService) {
|
||||
this.tamagotchiService = tamagotchiService;
|
||||
}
|
||||
|
||||
private static Color mapColor(String productId) {
|
||||
switch (productId) {
|
||||
case "66VCHSJNUP":
|
||||
return RED;
|
||||
default:
|
||||
return YELLOW;
|
||||
}
|
||||
}
|
||||
|
||||
@RequestMapping("/devices/{deviceId}")
|
||||
public Device getDevice(String deviceId) {
|
||||
return tamagotchiService.getDevice(deviceId);
|
||||
}
|
||||
|
||||
@RequestMapping("/devices")
|
||||
public Collection<Device> getDevices() {
|
||||
return tamagotchiService.getDevices();
|
||||
}
|
||||
|
||||
@PostMapping("/devices")
|
||||
public ResponseEntity createDevice(@RequestBody Collection<CreateDevicePayload> payload) {
|
||||
List<Device> devices = new ArrayList<>();
|
||||
for (CreateDevicePayload p : payload) {
|
||||
devices.add(tamagotchiService.createDevice(new Device(p.getOwner(), mapColor(p.getProductId()))));
|
||||
}
|
||||
return ok(devices);
|
||||
}
|
||||
|
||||
@RequestMapping("/_ah/warmup")
|
||||
public String warmup() {
|
||||
return "warming up";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Copyright (c) 2019, SAP SE, All rights reserved.
|
||||
*/
|
||||
package com.sap.tamagotchi.controller;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import com.sap.tamagotchi.model.Owner;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/owner")
|
||||
public class OwnerController {
|
||||
|
||||
@Autowired
|
||||
Owner owner;
|
||||
|
||||
@GetMapping()
|
||||
public void killTamagotchi() {
|
||||
owner.killRendomDevice();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.sap.tamagotchi.model;
|
||||
|
||||
public class Care {
|
||||
|
||||
private int feed = 0;
|
||||
private int pet = 0;
|
||||
|
||||
public int getFeed() {
|
||||
return feed;
|
||||
}
|
||||
|
||||
public void setFeed(int feed) {
|
||||
this.feed = feed;
|
||||
}
|
||||
|
||||
public int getPet() {
|
||||
return pet;
|
||||
}
|
||||
|
||||
public void setPet(int pet) {
|
||||
this.pet = pet;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.sap.tamagotchi.model;
|
||||
|
||||
public enum Color {
|
||||
RED, YELLOW, BLUE, GREEN
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.sap.tamagotchi.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class CreateDevicePayload {
|
||||
private final String userId;
|
||||
private final String productId;
|
||||
|
||||
@JsonCreator
|
||||
public CreateDevicePayload(@JsonProperty("userId") String userId, @JsonProperty("productId") String productId) {
|
||||
this.userId = userId;
|
||||
this.productId = productId;
|
||||
}
|
||||
|
||||
@JsonProperty("userId")
|
||||
public String getOwner() {
|
||||
return userId;
|
||||
}
|
||||
|
||||
@JsonProperty("productId")
|
||||
public String getProductId() {
|
||||
return productId;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package com.sap.tamagotchi.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class DefunctNotification implements IoTMessage {
|
||||
|
||||
@JsonProperty("message")
|
||||
private final String message;
|
||||
|
||||
public DefunctNotification(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getTopic() {
|
||||
return "tamagotchi-defunct";
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package com.sap.tamagotchi.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Queue;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class Device {
|
||||
|
||||
@JsonProperty("id")
|
||||
private final String id = UUID.randomUUID().toString();
|
||||
@JsonProperty("owner")
|
||||
private final String owner;
|
||||
@JsonProperty("color")
|
||||
private final Color color;
|
||||
@JsonProperty("born")
|
||||
private final Instant born = Instant.now();
|
||||
@JsonProperty("healthScore")
|
||||
private int healthScore = 100;
|
||||
private final Queue<IoTMessage> messages = new ConcurrentLinkedQueue<>();
|
||||
|
||||
public Device(String owner, Color color) {
|
||||
this.owner = owner;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@JsonProperty("id")
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@JsonProperty("owner")
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@JsonProperty("color")
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@JsonProperty("born")
|
||||
public String getBorn() {
|
||||
return born.toString();
|
||||
}
|
||||
|
||||
@JsonProperty("healthScore")
|
||||
public int getHealthScore() {
|
||||
return healthScore;
|
||||
}
|
||||
|
||||
@JsonProperty("isAlive")
|
||||
public boolean isAlive() {
|
||||
return healthScore > 1;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public void changeHealthScore(int delta) {
|
||||
int oldScore = healthScore;
|
||||
if (healthScore >= 1) {
|
||||
healthScore += delta;
|
||||
if (healthScore > 150)
|
||||
healthScore /= 10;
|
||||
}
|
||||
|
||||
if (healthScore < 1) {
|
||||
healthScore = 0;
|
||||
messages.add(new DeviceEvent(id, owner, color, born, healthScore, oldScore, Instant.now()));
|
||||
} else
|
||||
messages.add(new DeviceEvent(id, owner, color, born, healthScore, null, Instant.now()));
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public boolean hasMessages() {
|
||||
return !messages.isEmpty();
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
public Queue<IoTMessage> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package com.sap.tamagotchi.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
public class DeviceEvent implements IoTMessage {
|
||||
|
||||
@JsonProperty("id")
|
||||
private final String id;
|
||||
@JsonProperty("owner")
|
||||
private final String owner;
|
||||
@JsonProperty("color")
|
||||
private final Color color;
|
||||
@JsonProperty("born")
|
||||
private final Instant born;
|
||||
@JsonProperty("healthScore")
|
||||
private final Integer healthScore;
|
||||
@JsonProperty("lastHealthScore")
|
||||
private final Integer lastHealthScore;
|
||||
@JsonProperty("eventTime")
|
||||
private final Instant eventTime;
|
||||
|
||||
public DeviceEvent(String id, String owner, Color color, Instant born, Integer healthScore, Integer lastHealthScore, Instant eventTime) {
|
||||
this.id = id;
|
||||
this.owner = owner;
|
||||
this.color = color;
|
||||
this.born = born;
|
||||
this.healthScore = healthScore;
|
||||
this.lastHealthScore = lastHealthScore;
|
||||
this.eventTime = eventTime;
|
||||
}
|
||||
|
||||
@JsonProperty("id")
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@JsonProperty("owner")
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@JsonProperty("color")
|
||||
public Color getColor() {
|
||||
return color;
|
||||
}
|
||||
|
||||
@JsonProperty("born")
|
||||
public String getBorn() {
|
||||
return born.toString();
|
||||
}
|
||||
|
||||
@JsonProperty("healthScore")
|
||||
public Integer getHealthScore() {
|
||||
return healthScore;
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonProperty("lastHealthScore")
|
||||
public Integer getLastHealthScore() {
|
||||
return lastHealthScore;
|
||||
}
|
||||
|
||||
@JsonProperty("eventTime")
|
||||
public String getEventTime() {
|
||||
return eventTime.toString();
|
||||
}
|
||||
|
||||
@JsonProperty("isAlive")
|
||||
public boolean isAlive() {
|
||||
return healthScore > 1;
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
@Override
|
||||
public String getTopic() {
|
||||
return "tamagotchi-events";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeviceEvent{" +
|
||||
"id='" + id + '\'' +
|
||||
", owner='" + owner + '\'' +
|
||||
", color=" + color +
|
||||
", born=" + born +
|
||||
", healthScore=" + healthScore +
|
||||
", eventTime=" + eventTime +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.sap.tamagotchi.model;
|
||||
|
||||
public interface IoTMessage {
|
||||
String getTopic();
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* Copyright (c) 2019, SAP SE, All rights reserved.
|
||||
*/
|
||||
package com.sap.tamagotchi.model;
|
||||
|
||||
import static com.sap.tamagotchi.service.TamagotchiService.DEVICE_EVENT_PROCESSOR_SCHEDULE;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
import com.sap.tamagotchi.service.TamagotchiService;
|
||||
|
||||
@Service
|
||||
@EnableScheduling
|
||||
public class Owner {
|
||||
|
||||
private TamagotchiService tamagotchiService;
|
||||
|
||||
@Autowired
|
||||
public Owner(TamagotchiService tamagotchiService) {
|
||||
this.tamagotchiService = tamagotchiService;
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = DEVICE_EVENT_PROCESSOR_SCHEDULE)
|
||||
public void setData() {
|
||||
for (Device d : tamagotchiService.getDevices()) {
|
||||
|
||||
String userName = d.getOwner().substring(0, d.getOwner().indexOf("@")).toUpperCase();
|
||||
|
||||
int careAboutThePet = 0;
|
||||
|
||||
for (int i = 0; i < userName.length(); i++) {
|
||||
if (d.getColor().toString().indexOf(userName.charAt(i)) != -1) {
|
||||
careAboutThePet++;
|
||||
}
|
||||
}
|
||||
|
||||
Care care = new Care();
|
||||
|
||||
if (careAboutThePet == 0) {
|
||||
care.setFeed(-5);
|
||||
} else {
|
||||
care.setFeed(5);
|
||||
}
|
||||
tamagotchiService.takeCare(d.getId(), care);
|
||||
}
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 30000)
|
||||
public void killRendomDevice() {
|
||||
|
||||
Collection<Device> devices = tamagotchiService.getDevices();
|
||||
|
||||
if (devices != null && devices.iterator().hasNext()) {
|
||||
Device first = devices.iterator().next();
|
||||
Care care = new Care();
|
||||
care.setFeed(-100000);
|
||||
tamagotchiService.takeCare(first.getId(), care);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.sap.tamagotchi.publisher;
|
||||
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.google.api.core.ApiFuture;
|
||||
import com.google.api.core.ApiFutures;
|
||||
import com.google.cloud.ServiceOptions;
|
||||
import com.google.cloud.pubsub.v1.Publisher;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.pubsub.v1.ProjectTopicName;
|
||||
import com.google.pubsub.v1.PubsubMessage;
|
||||
import com.sap.tamagotchi.model.IoTMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PublisherService {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
// use the default project id
|
||||
private static final String PROJECT_ID = ServiceOptions.getDefaultProjectId();
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
@Autowired
|
||||
public PublisherService(ObjectMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
public void publish(IoTMessage message) throws Exception {
|
||||
if (message == null) {
|
||||
LOGGER.info("received null message");
|
||||
return;
|
||||
}
|
||||
String topicId = message.getTopic();
|
||||
ProjectTopicName topicName = ProjectTopicName.of(PROJECT_ID, topicId);
|
||||
Publisher publisher = null;
|
||||
List<ApiFuture<String>> futures = new ArrayList<>();
|
||||
|
||||
try {
|
||||
String stringMessage = mapper.writeValueAsString(message);
|
||||
// Create a publisher instance with default settings bound to the topic
|
||||
publisher = Publisher.newBuilder(topicName).build();
|
||||
LOGGER.info("publish to topic" + publisher.getTopicNameString());
|
||||
|
||||
// convert message to bytes
|
||||
ByteString data = ByteString.copyFromUtf8(stringMessage);
|
||||
PubsubMessage pubsubMessage = PubsubMessage.newBuilder()
|
||||
.setData(data)
|
||||
.build();
|
||||
|
||||
LOGGER.info("publish to message" + stringMessage);
|
||||
|
||||
// Schedule a message to be published. Messages are automatically batched.
|
||||
ApiFuture<String> future = publisher.publish(pubsubMessage);
|
||||
futures.add(future);
|
||||
|
||||
} finally {
|
||||
// Wait on any pending requests
|
||||
List<String> messageIds = ApiFutures.allAsList(futures).get();
|
||||
|
||||
for (String messageId : messageIds) {
|
||||
System.out.println(messageId);
|
||||
LOGGER.info("publish successful : " + messageId);
|
||||
}
|
||||
|
||||
if (publisher != null) {
|
||||
// When finished with the publisher, shutdown to free up resources.
|
||||
publisher.shutdown();
|
||||
}
|
||||
|
||||
if (messageIds.isEmpty())
|
||||
LOGGER.info("no messages published ");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package com.sap.tamagotchi.service;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.sap.tamagotchi.model.Care;
|
||||
import com.sap.tamagotchi.model.DefunctNotification;
|
||||
import com.sap.tamagotchi.model.Device;
|
||||
import com.sap.tamagotchi.publisher.PublisherService;
|
||||
|
||||
@Service
|
||||
@EnableScheduling
|
||||
public class TamagotchiService {
|
||||
|
||||
public static final long DEVICE_EVENT_PROCESSOR_SCHEDULE = 5000;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
|
||||
private static final Map<String, Device> deviceRegistry = Collections.synchronizedMap(new HashMap<>());
|
||||
|
||||
private final PublisherService publisherService;
|
||||
|
||||
@Autowired
|
||||
public TamagotchiService(PublisherService publisherService) {
|
||||
this.publisherService = publisherService;
|
||||
}
|
||||
|
||||
public Device getDevice(String deviceId) {
|
||||
return deviceRegistry.get(deviceId);
|
||||
}
|
||||
|
||||
public Collection<Device> getDevices() {
|
||||
return deviceRegistry.values();
|
||||
}
|
||||
|
||||
public Set<String> getDeviceIds() {
|
||||
return deviceRegistry.keySet();
|
||||
}
|
||||
|
||||
public Device createDevice(Device device) {
|
||||
deviceRegistry.put(device.getId(), device);
|
||||
return device;
|
||||
}
|
||||
|
||||
public void takeCare(String deviceId, Care care) {
|
||||
Device device = deviceRegistry.get(deviceId);
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
device.changeHealthScore(care.getFeed());
|
||||
device.changeHealthScore(care.getPet());
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = DEVICE_EVENT_PROCESSOR_SCHEDULE)
|
||||
private void processDeviceEvents() {
|
||||
deviceRegistry
|
||||
.values()
|
||||
.parallelStream()
|
||||
.filter(Device::hasMessages)
|
||||
.forEach(device -> {
|
||||
while (device.getMessages().peek() != null) {
|
||||
try {
|
||||
publisherService.publish(device.getMessages().poll());
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("processing device events failed: {}", ex.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// remove dead devices
|
||||
deviceRegistry
|
||||
.values()
|
||||
.parallelStream()
|
||||
.filter(device -> !device.isAlive())
|
||||
.forEach(device -> {
|
||||
sendTamagotchiDefunctNotifiction(device.getId());
|
||||
deviceRegistry.remove(device.getId());
|
||||
LOGGER.info("{} has died", device.getId());
|
||||
});
|
||||
}
|
||||
|
||||
private void sendTamagotchiDefunctNotifiction(String id) {
|
||||
|
||||
Device device = deviceRegistry.get(id);
|
||||
if (device == null || device.getId() == null || device.getOwner() == null) {
|
||||
return;
|
||||
}
|
||||
String defunctMessage = String.format("Tamagotchi %s of %s passed away", device.getId(), device.getOwner());
|
||||
DefunctNotification defunctNotification = new DefunctNotification(defunctMessage);
|
||||
try {
|
||||
publisherService.publish(defunctNotification);
|
||||
LOGGER.info("defunct notification sent for {}", device.getId());
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("sendTamagotchiDefunctNotifiction failed: {}", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Copyright (c) 2019, SAP SE, All rights reserved.
|
||||
*/
|
||||
package com.sap.tamagotchi.model;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.mockito.Mockito.when;
|
||||
import java.util.Collection;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.mock.mockito.MockBean;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import com.sap.tamagotchi.service.TamagotchiService;;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest
|
||||
public class OwnerTest {
|
||||
|
||||
@Autowired
|
||||
Owner owner;
|
||||
|
||||
@MockBean
|
||||
TamagotchiService tamagotchiService;
|
||||
|
||||
Collection<Device> mockDevices;
|
||||
|
||||
// @Before
|
||||
// public void init() {
|
||||
// MockitoAnnotations.initMocks(this);
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testIt() {
|
||||
when(tamagotchiService.getDevices()).thenReturn(asList(new Device("elisa@sap.com", Color.BLUE)));
|
||||
owner.setData();
|
||||
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue