Giter Site home page Giter Site logo

demo-service-181's People

Contributors

afterbvrner avatar cakenumber1 avatar destrolaric avatar dimonstad avatar erartria avatar github-actions[bot] avatar joiner-dot avatar julesadikhanyan avatar kot1que avatar kuzznya avatar madzhidov avatar onlyoneuseacc avatar panoni avatar shchuko avatar tulesha avatar valtornist99 avatar vas9ka avatar xeniasv avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

demo-service-181's Issues

Delivery service: дописать и исправить тесты

После рефакторинга сервиса и изменения семантики часть тестов начала падать и была отключена аннотацией @Disabled. Надо бы переписать их и включить обратно.

Add external system integration to the notification service

Detailed task description can be found here. The external system documentation placed by this link, the whole API documentation is in already known place.

It's preferable to reuse already created classes from the packages:

  • com.itmo.microservices.shop.common.externalservice
  • com.itmo.microservices.shop.common.transactions
  • com.itmo.microservices.shop.common.executors

Usage example of these mechanisms can be found in the payment service (diff: 1bcff1a)

Pass order service events to logger and notification service

Each action in each service must generate an Event for the logger to catch. Also, some of evens should be passed to Notification Service. See the example below.

  1. Create a notable events for our logger:
package com.itmo.microservices.demo.users.impl.logging;

import com.itmo.microservices.commonlib.logging.NotableEvent;
import org.jetbrains.annotations.NotNull;

public enum UserServiceNotableEvents implements NotableEvent {
    I_USER_CREATED("User created: {}");

    private final String template;

    UserServiceNotableEvents(String template) {
        this.template = template;
    }

    @NotNull
    @Override
    public String getName() {
        return this.name();
    }

    @NotNull
    @Override
    public String getTemplate() {
        return this.template;
    }
}
  1. Create event classes for notification service:
package com.itmo.microservices.demo.user.api.messaging;

import com.itmo.microservices.shop.demo.api.model.UserModel;

public class UserCreatedEvent {
    private final UserModel userModel;

    public UserCreatedEvent(UserModel userModel) {
        this.userModel = userModel;
    }

    public UserModel getUserModel() {
        return userModel;
    }
}
  1. And pass them to event bus:
package com.itmo.microservices.demo.users.impl.service;

import com.google.common.eventbus.EventBus;

import com.itmo.microservices.commonlib.annotations.InjectEventLogger;
import com.itmo.microservices.commonlib.logging.EventLogger;
import com.itmo.microservices.shop.user.impl.logging.UserServiceNotableEvents;
import com.itmo.microservices.shop.user.api.messaging.UserCreatedEvent;
import com.itmo.microservices.shop.user.api.model.RegistrationRequest;

@Service
@Suppress("UnstableApiUsage") /* Suppress warning about unstable event bus */
public class DefaultUserService  {
    @InjectEventLogger
    private EventLogger eventLogger;
    private final EventBus eventBus;

    public UserService(EventBus eventBus) {
        this.eventBus = eventBus;
    }

    @Override
    public void registerUser(RegistrationRequest request) {
        /* Your service code here */
        var user = createUser(request);
 
        /* Passing the event to logger */
        if (eventLogger != null) {
            eventLogger.info(UserServiceNotableEvents.I_USER_CREATED, user.getUsername());
        }

        
        /* Passing the event to logger */
         eventBus.post(new UserCreatedEvent(user));
    }
}

Delivery service: реализовать запись лога доставки в базу данных

Сейчас лог доставки пишется примитивно в ArrayList. Надо бы создать таблицу в БД и писать его туда
Зачем оно вообще надо - см. документацию к api, endpoint - GET /_internal/deliveryLog/{orderId}.
Скорее всего надо будет поправить модельку (не пихать в нее ненужный order id - сейчас заигнорен через @JsonIgnore, и поправить сам контроллер. Постараться сделать так, чтобы не было идейских ворнингов.

Connect order and delivery service

  • create events for start and end delivery fields orderUUID, timeSlot, userUUID
  • create event for canceled delivery
  • create @Subscribe for this events

Catalog service: дописать и исправить тесты

После рефакторинга сервиса и изменения семантики часть тестов начала падать и была отключена аннотацией @Disabled. Надо бы переписать их и включить обратно.

Connect order and catalog service

ItemService:

  • create getItemByUUID
  • add method for booking Items bookItems(Map<UUID, Integer>) -> List[UUID] - faild items
  • add method for removing booking deleteBooking(Map<UUID, Integer>) -> void

OrderService:

  • integrate this methods to order service

Order service: дописать и исправить тесты

После рефакторинга сервиса и изменения семантики часть тестов начала падать и была отключена аннотацией @Disabled. Надо бы переписать их и включить обратно.

Add rate limiter to polling transaction processor

We have unified transaction processor for external service polling interaction. Now we should have a rate limiter to prevent external service overloading.

Expected usage example:

// Setup the rate limiter: 500 requests per second accepted
var rateLimiter = new RateLimiter(500, TimeUnit.SECONDS); 

// And connect it to `TransactionPollingProcessor`
var pollingTransactionProcessor = TransactionPollingProcessor.<[...], [...], [...]>builder()
      .withPollingExecutorService([...])
      .withTransactionStarter([...])
      .withTransactionUpdater([...])
      .withTransactionFinishHandler([...])
      .withTransactionStartRateLimiter(rateLimiter) /* !!! Pay attention to here !!! */
      .build();


// Use transaction processor with the rate limiter
// When we hit rate limit, it's expected 'TransactionStartException' to be thrown.
TransactionWrapper<[...]> result = null;
try {
      result = pollingTransactionProcessor.startTransaction(context);
} catch (TransactionStartException e) {
     /* !!! We should get here on rate limit exceeding !!! */
}

The study course lecture about limiter can be helpful.

itmo-central and itmo-snapshots return '401 Unathorized' periodically

IDEA Log:

[WARNING] Failure to transfer com.itmo.microservices:common-lib:0.5.0-SNAPSHOT/maven-metadata.xml from http://77.234.215.138:30031/artifactory/libs-snapshot was cached in the local repository, resolution will not be reattempted until the update interval of itmo-snapshots has elapsed or updates are forced. Original error: Could not transfer metadata com.itmo.microservices:common-lib:0.5.0-SNAPSHOT/maven-metadata.xml from/to itmo-snapshots (http://77.234.215.138:30031/artifactory/libs-snapshot): Authentication failed for http://77.234.215.138:30031/artifactory/libs-snapshot/com/itmo/microservices/common-lib/0.5.0-SNAPSHOT/maven-metadata.xml 401 Unauthorized

Can be useful:
https://t.me/c/1436658303/500
https://t.me/c/1436658303/523
https://t.me/c/1436658303/1105
https://t.me/c/1436658303/1109

Pass catalog service events to logger and notification service

Each action in each service must generate an Event for the logger to catch. Also, some of evens should be passed to Notification Service. See the example below.

  1. Create a notable events for our logger:
package com.itmo.microservices.demo.users.impl.logging;

import com.itmo.microservices.commonlib.logging.NotableEvent;
import org.jetbrains.annotations.NotNull;

public enum UserServiceNotableEvents implements NotableEvent {
    I_USER_CREATED("User created: {}");

    private final String template;

    UserServiceNotableEvents(String template) {
        this.template = template;
    }

    @NotNull
    @Override
    public String getName() {
        return this.name();
    }

    @NotNull
    @Override
    public String getTemplate() {
        return this.template;
    }
}
  1. Create event classes for notification service:
package com.itmo.microservices.demo.user.api.messaging;

import com.itmo.microservices.shop.demo.api.model.UserModel;

public class UserCreatedEvent {
    private final UserModel userModel;

    public UserCreatedEvent(UserModel userModel) {
        this.userModel = userModel;
    }

    public UserModel getUserModel() {
        return userModel;
    }
}
  1. And pass them to event bus:
package com.itmo.microservices.demo.users.impl.service;

import com.google.common.eventbus.EventBus;

import com.itmo.microservices.commonlib.annotations.InjectEventLogger;
import com.itmo.microservices.commonlib.logging.EventLogger;
import com.itmo.microservices.shop.user.impl.logging.UserServiceNotableEvents;
import com.itmo.microservices.shop.user.api.messaging.UserCreatedEvent;
import com.itmo.microservices.shop.user.api.model.RegistrationRequest;

@Service
@Suppress("UnstableApiUsage") /* Suppress warning about unstable event bus */
public class DefaultUserService  {
    @InjectEventLogger
    private EventLogger eventLogger;
    private final EventBus eventBus;

    public UserService(EventBus eventBus) {
        this.eventBus = eventBus;
    }

    @Override
    public void registerUser(RegistrationRequest request) {
        /* Your service code here */
        var user = createUser(request);
 
        /* Passing the event to logger */
        if (eventLogger != null) {
            eventLogger.info(UserServiceNotableEvents.I_USER_CREATED, user.getUsername());
        }

        
        /* Passing the event to logger */
         eventBus.post(new UserCreatedEvent(user));
    }
}

Connect order and payment service

  • create event for paying with fields id, time, money
  • create event for notification about successful/unsuccessful payment
  • create @Subscribe for notification

Payment Service

  • Refund:
    1 ) Events: RefundOrderRequestEvent, RefundOrderAnswerEvent
    2 ) Service\Subscribe: handleRefund(RefundOrderRequestEvent ... )
    3 ) Service\Scheduled: doRefund()
    4 ) Entity: RefundOrder
    5 ) Repository: RefundOrderRepository
    6 ) Logging: PaymentServiceNotableEvent
    7 ) Model: RefundOrderDto implements Comparable<RefundOrderDto>

Order Service

  • Subscribe: handleRefundAnswer(RefundOrderAnswerEvent event)
  • EventBus::post(event) | event <-- RefundOrderRequestEvent.class

Tests. Pass fake authentication

Example how to use @WithMockCustomUser notation:

    @Test
    public void whenUpdateItemWithoutAuthentication_thenReturnStatusForbidden() throws Exception {
        Mockito.doNothing().when(itemService).updateItem(isA(UUID.class), isA(ItemDTO.class));

        final String requestedBodyContent = mapper.writeValueAsString(hardcodedValues.mockedItemDTO);

        this.mockMvc.perform(put("/items/{id}", UUID.randomUUID())
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(requestedBodyContent))
                .andDo(print())
                .andExpect(status().isForbidden());

        Mockito.verifyNoInteractions(itemService);
    }

    @Test
    @WithMockCustomUser
    public void whenUpdateItemWithAccessAuthority_thenReturnStatusForbidden() throws Exception {
        Mockito.doNothing().when(itemService).updateItem(isA(UUID.class), isA(ItemDTO.class));

        final String requestedBodyContent = mapper.writeValueAsString(hardcodedValues.mockedItemDTO);

        this.mockMvc.perform(put("/items/{id}", UUID.randomUUID())
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(requestedBodyContent))
                .andDo(print())
                .andExpect(status().isForbidden());

        Mockito.verifyNoInteractions(itemService);
    }

    @Test
    @WithMockCustomUser(roles = {"ACCESS", "ADMIN"})
    public void whenUpdateItemWithAdminAuthority_thenReturnStatusOK() throws Exception {
        Mockito.doNothing().when(itemService).updateItem(isA(UUID.class), isA(ItemDTO.class));

        final String requestedBodyContent = mapper.writeValueAsString(hardcodedValues.mockedItemDTO);

        this.mockMvc.perform(put("/items/{id}", UUID.randomUUID())
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(requestedBodyContent))
                .andDo(print())
                .andExpect(status().isOk());

        Mockito.verify(itemService).updateItem(Mockito.any(UUID.class), Mockito.any(ItemDTO.class));
        Mockito.verifyNoMoreInteractions(itemService);
    }

Add external system integration to the delivery service

Detailed task description can be found here. The external system documentation placed by this link, the whole API documentation is in already known place.

It's preferable to reuse already created classes from the packages:

  • com.itmo.microservices.shop.common.externalservice
  • com.itmo.microservices.shop.common.transactions
  • com.itmo.microservices.shop.common.executors

Usage example of these mechanisms can be found in the payment service (diff: 1bcff1a)

Improve booking mechanisms

Please provide:

  • unique booking id generation on booking (see BookingDto)
  • booking history storage (BookingLogRecord)
  • method to book items that returns at lease booking id
  • method to undo booking by booking id
  • method to describe booking by by booking id

If needed, it's allowed to add new columns to existing db tables and create new ones.

Order service: реализовать сгорание заказа (переход в статус DISCARD)

В машине состояний заказ должен переходить COLLECTING -> DISCARD по таймауту бездействия.

  • Реализовать можно аналогично "сгоранию" времени на оплату через ScheduledThreadPoolExecutor, см. payment service
  • Пусть время на сбоку заказа будет установлено в 1 час, после дискардим.
  • Стоит быть осторожным, случайно не отменить заказ, если пользователь его всё-таки поменял. Возможно, в бд можно добавить новый атрибут last_modified для заказа

Payment service: дописать и исправить тесты

После рефакторинга сервиса и изменения семантики часть тестов начала падать и была отключена аннотацией @Disabled. Надо бы переписать их и включить обратно.

Pass delivery service events to logger

Each action in each service must generate an Event for the logger to catch. See an example below.

Create a notable events enum for your service:

import com.itmo.microservices.commonlib.logging.NotableEvent;
import org.jetbrains.annotations.NotNull;

public enum UserServiceNotableEvents implements NotableEvent {
    I_USER_CREATED("User created: {}");

    private final String template;

    UserServiceNotableEvents(String template) {
        this.template = template;
    }

    @NotNull
    @Override
    public String getName() {
        return this.name();
    }

    @NotNull
    @Override
    public String getTemplate() {
        return this.template;
    }
}

And use it:

import com.itmo.microservices.commonlib.annotations.InjectEventLogger;
import com.itmo.microservices.commonlib.logging.EventLogger;
import com.itmo.microservices.shop.user.impl.logging.UserServiceNotableEvents;

@Service
public class DefaultUserService  {
    @InjectEventLogger
    private EventLogger eventLogger;

    @Override
    public void registerUser(RegistrationRequest request) {
        /* Your service code here */
        if (eventLogger != null) {
            eventLogger.info(UserServiceNotableEvents.I_USER_CREATED, user.getUsername());
        }
    }
}

Pass user service events to logger and notification service

Each action in each service must generate an Event for the logger to catch. Also, some of evens should be passed to Notification Service. See the example below.

  1. Create a notable events for our logger:
package com.itmo.microservices.demo.users.impl.logging;

import com.itmo.microservices.commonlib.logging.NotableEvent;
import org.jetbrains.annotations.NotNull;

public enum UserServiceNotableEvents implements NotableEvent {
    I_USER_CREATED("User created: {}");

    private final String template;

    UserServiceNotableEvents(String template) {
        this.template = template;
    }

    @NotNull
    @Override
    public String getName() {
        return this.name();
    }

    @NotNull
    @Override
    public String getTemplate() {
        return this.template;
    }
}
  1. Create event classes for notification service:
package com.itmo.microservices.demo.user.api.messaging;

import com.itmo.microservices.shop.demo.api.model.UserModel;

public class UserCreatedEvent {
    private final UserModel userModel;

    public UserCreatedEvent(UserModel userModel) {
        this.userModel = userModel;
    }

    public UserModel getUserModel() {
        return userModel;
    }
}
  1. And pass them to event bus:
package com.itmo.microservices.demo.users.impl.service;

import com.google.common.eventbus.EventBus;

import com.itmo.microservices.commonlib.annotations.InjectEventLogger;
import com.itmo.microservices.commonlib.logging.EventLogger;
import com.itmo.microservices.shop.user.impl.logging.UserServiceNotableEvents;
import com.itmo.microservices.shop.user.api.messaging.UserCreatedEvent;
import com.itmo.microservices.shop.user.api.model.RegistrationRequest;

@Service
@Suppress("UnstableApiUsage") /* Suppress warning about unstable event bus */
public class DefaultUserService  {
    @InjectEventLogger
    private EventLogger eventLogger;
    private final EventBus eventBus;

    public UserService(EventBus eventBus) {
        this.eventBus = eventBus;
    }

    @Override
    public void registerUser(RegistrationRequest request) {
        /* Your service code here */
        var user = createUser(request);
 
        /* Passing the event to logger */
        if (eventLogger != null) {
            eventLogger.info(UserServiceNotableEvents.I_USER_CREATED, user.getUsername());
        }

        
        /* Passing the event to logger */
         eventBus.post(new UserCreatedEvent(user));
    }
}

Order controller returns invalid OrderDto

Endpoint: GET /orders/$orderId

Actual invalid response:

{
	"id": "5ccaccd8-7c9f-4ded-8650-135077678e49",
	"timeCreated": 1637426853,
	"status": "COLLECTING",
	"itemsMap": {
		"OrderItemDTO(id=3cd3283b-e057-406a-bb64-5c8a24c9be93, title=mock name, price=0)": 16,
		"OrderItemDTO(id=f72fe1ff-c59f-4879-8ba2-afa6b5d63e02, title=mock name2, price=0)": 23  
	},
	"deliveryDuration": 0,
	"paymentHistory": []
}

which is expected to be:

{
	"id": "5ccaccd8-7c9f-4ded-8650-135077678e49",
	"timeCreated": 1637426853,
	"status": "COLLECTING",
	"itemsMap": {
		"i3cd3283b-e057-406a-bb64-5c8a24c9be93": 16,
		"f72fe1ff-c59f-4879-8ba2-afa6b5d63e02": 23
	},
	"deliveryDuration": 0,
	"paymentHistory": []
}

See API description

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.