Skip to content

Commit

Permalink
feat: implement event module (#14)
Browse files Browse the repository at this point in the history
feat: implement scheduling and event module
  • Loading branch information
mohsenk authored Nov 18, 2024
1 parent 8dd8878 commit f1c5549
Show file tree
Hide file tree
Showing 68 changed files with 1,545 additions and 129 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ group = 'app.teamwize'
version = '0.9.0'

java {
sourceCompatibility = JavaVersion.VERSION_17
sourceCompatibility = JavaVersion.VERSION_21
}

configurations {
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
8 changes: 5 additions & 3 deletions src/main/java/app/teamwize/api/Application.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package app.teamwize.api.auth.domain.event;

import app.teamwize.api.event.model.EventPayload;
import app.teamwize.api.event.model.EventType;

import java.util.Map;

public record OrganizationCreatedEvent(UserEventPayload user,
OrganizationEventPayload organization) implements EventPayload {
@Override
public EventType name() {
return EventType.ORGANIZATION_CREATED;
}

@Override
public Map<String, Object> payload() {
return Map.of(
"organization", organization,
"user", user
);
}



}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package app.teamwize.api.auth.domain.event;

import app.teamwize.api.organization.domain.entity.Organization;

public record OrganizationEventPayload(Long id, String name) {
public OrganizationEventPayload(Organization organization) {
this(organization.getId(), organization.getName());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package app.teamwize.api.auth.domain.event;

import app.teamwize.api.user.domain.UserRole;
import app.teamwize.api.user.domain.entity.User;

public record UserEventPayload(
Long id,
UserRole role,
String email,
String password,
String phone,
String firstName,
String lastName,
String country,
String timezone) {

public UserEventPayload(User user) {
this(user.getId(),
user.getRole(),
user.getEmail(),
user.getPassword(),
user.getPhone(),
user.getFirstName(),
user.getLastName(),
user.getCountry(),
user.getTimezone()
);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package app.teamwize.api.auth.service;


import app.teamwize.api.auth.domain.event.OrganizationCreatedEvent;
import app.teamwize.api.auth.domain.event.OrganizationEventPayload;
import app.teamwize.api.auth.domain.event.UserEventPayload;
import app.teamwize.api.auth.domain.request.LoginRequest;
import app.teamwize.api.base.exception.BaseException;
import app.teamwize.api.event.service.EventService;
import app.teamwize.api.leave.exception.LeaveTypeNotFoundException;
import app.teamwize.api.leave.service.LeavePolicyService;
import app.teamwize.api.organization.mapper.OrganizationMapper;
import app.teamwize.api.organization.service.OrganizationService;
import app.teamwize.api.user.domain.request.AdminUserCreateRequest;
import app.teamwize.api.user.exception.UserAlreadyExistsException;
Expand All @@ -15,14 +20,12 @@
import app.teamwize.api.auth.domain.response.AuthenticationResponse;
import app.teamwize.api.auth.exception.InvalidCredentialException;
import app.teamwize.api.organization.domain.event.OrganizationCreateRequest;
import app.teamwize.api.organization.domain.event.OrganizationCreatedEvent;
import app.teamwize.api.organization.exception.OrganizationNotFoundException;
import app.teamwize.api.team.domain.exception.TeamNotFoundException;
import app.teamwize.api.team.domain.request.TeamCreateRequest;
import app.teamwize.api.team.service.TeamService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
Expand All @@ -38,10 +41,10 @@ public class AuthenticationService implements UserDetailsService {
private final OrganizationService organizationService;
private final TokenService tokenService;
private final UserService userService;
private final ApplicationEventPublisher eventPublisher;
private final UserMapper userMapper;
private final TeamService teamService;
private final LeavePolicyService leavePolicyService;
private final EventService eventService;


@Transactional(rollbackFor = BaseException.class)
Expand All @@ -61,7 +64,11 @@ public AuthenticationResponse register(RegistrationRequest request) throws UserA
);

var user = userService.createOrganizationAdmin(organization.getId(), team.getId(), registerRequest);
eventPublisher.publishEvent(new OrganizationCreatedEvent(organization, userMapper.toUserResponse(user)));

eventService.emmit(organization.getId(), new OrganizationCreatedEvent(
new UserEventPayload(user),
new OrganizationEventPayload(organization)
));


var accessToken = tokenService.generateAccessToken(
Expand Down Expand Up @@ -102,13 +109,4 @@ public UserDetails loadUserByUsername(String userId) throws UsernameNotFoundExce
}
}

// public ApiKeyValidateResponse validateApiKey(ApiKeyValidateRequest request) throws ApiKeyNotFoundException {
// var apiKey = apiKeyService.findByKey(request.getApiKey());
// var site = siteService.getOrganizationDefaultSite(apiKey.getOrganizationId());
//
// return new ApiKeyValidateResponse()
// .setOrganizationId(apiKey.getOrganizationId())
// .setSiteId(site.getId());
// }

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
@Setter
@MappedSuperclass
@EntityListeners({AuditingEntityListener.class})
//@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
//@TypeDef(name = "list-array", typeClass = ListArrayType.class)
//@TypeDef(typeClass = PostgreSQLIntervalType.class, defaultForType = Duration.class)
public class BaseAuditEntity {
@CreatedDate
@Column(name = "created_at", updatable = false)
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/app/teamwize/api/base/domain/model/Paged.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package app.teamwize.api.base.domain.model;

import jakarta.annotation.Nonnull;
import lombok.With;

import java.util.List;

@With
public record Paged<T>(
@Nonnull
List<T> contents,
@Nonnull
Integer pageNumber,
@Nonnull
Integer pageSize,
@Nonnull
Integer totalPages,
@Nonnull
Long totalContents) {


public Paged(List<T> contents, Integer pageNumber, Integer pageSize, Long totalContents) {
this(contents, pageNumber, pageSize,
(int) Math.ceil((double) totalContents / pageSize), // Calculate totalPages
totalContents);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package app.teamwize.api.base.domain.model;

public record Pagination(Integer pageNumber,Integer pageSize) {
}
Original file line number Diff line number Diff line change
@@ -1,26 +1,25 @@
package app.teamwize.api.base.domain.model.response;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import jakarta.annotation.Nonnull;
import java.util.List;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class PagedResponse<T> {
@Nonnull
List<T> contents;
import java.util.List;

@Nonnull
Integer pageNumber;
@Nonnull
Integer pageSize;
@Nonnull
Integer totalPages;
@Nonnull
Long totalContents;
public record PagedResponse<T>(
@Nonnull
List<T> contents,
@Nonnull
Integer pageNumber,
@Nonnull
Integer pageSize,
@Nonnull
Integer totalPages,
@Nonnull
Long totalContents) {

public PagedResponse(List<T> contents, Integer pageNumber, Integer pageSize, Long totalContents) {
this(contents, pageNumber, pageSize,
(int) Math.ceil((double) totalContents / pageSize), // Calculate totalPages
totalContents);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package app.teamwize.api.base.jpa;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import io.hypersistence.utils.hibernate.type.util.ObjectMapperSupplier;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

public class HibernateJacksonMapperSupplier implements ObjectMapperSupplier {

@Override
public ObjectMapper get() {
var timeModule = new JavaTimeModule();

return Jackson2ObjectMapperBuilder.json()
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.failOnUnknownProperties(false)
.failOnEmptyBeans(false)
.modules(timeModule)
.build();
}
}
7 changes: 7 additions & 0 deletions src/main/java/app/teamwize/api/base/util/StringUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package app.teamwize.api.base.util;

public class StringUtils {
public static String toSnakeCase(String className) {
return className.replaceAll("([a-z])([A-Z])", "$1_$2").toLowerCase();
}
}
47 changes: 47 additions & 0 deletions src/main/java/app/teamwize/api/event/entity/EventEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package app.teamwize.api.event.entity;

import app.teamwize.api.base.domain.entity.BaseAuditEntity;
import app.teamwize.api.event.model.EventStatus;
import app.teamwize.api.event.model.EventType;
import app.teamwize.api.organization.domain.entity.Organization;
import io.hypersistence.utils.hibernate.type.json.JsonType;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.Type;

import java.time.Instant;
import java.util.List;
import java.util.Map;


@Getter
@Setter
@Entity
@Table(name = "events")
public class EventEntity extends BaseAuditEntity {
@Id
@GeneratedValue(generator = "event_id_seq_gen")
@SequenceGenerator(name = "event_id_seq_gen", sequenceName = "event_id_seq", allocationSize = 10)
private Long id;

@Enumerated(EnumType.STRING)
private EventType type;

@Type(JsonType.class)
private Map<String, Object> params;

@Enumerated(EnumType.STRING)
private EventStatus status;

private Byte maxAttempts;

private Instant scheduledAt;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "organization_id")
private Organization organization;

@OneToMany(mappedBy = "event")
private List<EventExecutionEntity> executions;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package app.teamwize.api.event.entity;

import app.teamwize.api.base.domain.entity.BaseAuditEntity;
import app.teamwize.api.event.model.EventExecutionStatus;
import app.teamwize.api.event.model.EventExitCode;
import io.hypersistence.utils.hibernate.type.json.JsonType;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.Type;

import java.util.Map;


@Getter
@Setter
@Entity
@Table(name = "event_executions")
public class EventExecutionEntity extends BaseAuditEntity {
@Id
@GeneratedValue(generator = "event_execution_id_seq_gen")
@SequenceGenerator(name = "event_execution_id_seq_gen", sequenceName = "event_execution_id_seq", allocationSize = 10)
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "event_id")
private EventEntity event;

@Enumerated(EnumType.STRING)
private EventExecutionStatus status;

@Enumerated(EnumType.STRING)
private EventExitCode exitCode;

private Integer attempts;

private String handler;

@Type(JsonType.class)
@Column(columnDefinition = "jsonb")
private Map<String, Object> metadata;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package app.teamwize.api.event.exception;

import app.teamwize.api.base.exception.BaseException;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
public class EventNotFoundException extends BaseException {

private final Long id;

}
Loading

0 comments on commit f1c5549

Please sign in to comment.