wiki:appdevelopment

Version 4 (modified by 231175, 2 days ago) ( diff )

--

Напреден Апликативен Развој

Трансакции

Креирање на курс

    @Transactional
    @Override
    public CourseVersion createCourse(CourseDtoFull courseDtoFull) {
        Language language = courseDtoFull.getLanguage();

        Course course = buildCourse(courseDtoFull, language);

        CourseVersion oldCourseVersion = courseVersionRepository
                .findByActiveTrueAndCourse_Id(course.getId());

        int newVersionNumber = 1;
        if (oldCourseVersion != null) {
            newVersionNumber = oldCourseVersion.getVersionNumber() + 1;
            oldCourseVersion.setActive(false);
            courseVersionRepository.save(oldCourseVersion);
        }

        CourseVersion courseVersion = CourseVersion.builder()
                .versionNumber(newVersionNumber)
                .active(true)
                .creationDate(java.time.LocalDate.now())
                .course(course)
                .build();

        List<CourseContent> contentList = courseDtoFull.getCourseContents().stream()
                .map(content -> courseContentService.buildCourseContent(content, courseVersion, language))
                .toList();

        courseVersion.setCourseContents(contentList);

        List<Tag> skillTags =  tagService.processRawTags(
                courseDtoFull.getSkillsGained(), TagType.SKILL, language
        );
        List<Tag> topicTags = tagService.processRawTags(
                courseDtoFull.getTopicsCovered(), TagType.TOPIC, language
        );

        List<Tag> tagList = new ArrayList<>(skillTags);
        tagList.addAll(topicTags);

        course.setTags(tagList);

        return courseVersionRepository.save(courseVersion);
    }

    private Course buildCourse(CourseDtoFull courseDtoFull, Language language) {

        int durationMinutes = courseDtoFull.getCourseContents().stream()
                .flatMap(content -> content.getCourseLectures().stream())
                .mapToInt(CourseLectureDtoFull::getDurationMinutes)
                .sum();

        Course course = Course.builder()
                .imageUrl(courseDtoFull.getImageUrl())
                .color(courseDtoFull.getColor())
                .difficulty(courseDtoFull.getDifficulty())
                .durationMinutes(durationMinutes)
                .price(courseDtoFull.getPrice())
                .build();

        CourseTranslate courseTranslate = CourseTranslate.builder()
                .language(language)
                .titleShort(courseDtoFull.getTitleShort())
                .title(courseDtoFull.getTitle())
                .descriptionShort(courseDtoFull.getDescriptionShort())
                .description(courseDtoFull.getDescription())
                .descriptionLong(courseDtoFull.getDescriptionLong())
                .whatWillBeLearned(courseDtoFull.getWhatWillBeLearned())
                .course(course)
                .build();

        course.setTranslations(List.of(courseTranslate));
        return course;
    }

Преведување на постоечки курс

    @Transactional
    @Override
    public Course translateCourse(CourseTranslateReq courseTranslateReq) {
        validate.validateCourseExists(courseTranslateReq.getId());
        validate.validateCourseTranslation(courseTranslateReq.getId(), courseTranslateReq.getLanguage());

        CourseVersion courseVersion = courseVersionRepository.findByActiveTrueAndCourse_Id(courseTranslateReq.getId());
        Course course = courseRepository.findById(courseTranslateReq.getId()).orElseThrow();
        addCourseTranslation(course, courseTranslateReq);
        translateContents(courseVersion, courseTranslateReq.getCourseContents(), courseTranslateReq.getLanguage());

        tagService.processExistingTags(
                courseTranslateReq.getSkillsGained(), TagType.SKILL, courseTranslateReq.getLanguage()
        );
        tagService.processExistingTags(
                courseTranslateReq.getTopicsCovered(), TagType.TOPIC, courseTranslateReq.getLanguage()
        );

        return courseRepository.save(course);
    }

    private void addCourseTranslation(Course course, CourseTranslateReq dto) {
        CourseTranslate translation = CourseTranslate.builder()
                .language(dto.getLanguage())
                .titleShort(dto.getTitleShort())
                .title(dto.getTitle())
                .descriptionShort(dto.getDescriptionShort())
                .description(dto.getDescription())
                .descriptionLong(dto.getDescriptionLong())
                .whatWillBeLearned(dto.getWhatWillBeLearned())
                .course(course)
                .build();

        course.getTranslations().add(translation);
    }

    private void translateContents(CourseVersion courseVersion, List<CourseContentTranslateReq> contentDtos, Language language) {
        for (CourseContent content : courseVersion.getCourseContents()) {
            CourseContentTranslateReq contentDto = contentDtos.stream()
                    .filter(ct -> ct.getId().equals(content.getId()))
                    .findFirst()
                    .orElseThrow(() -> new RuntimeException(
                            "Missing translation DTO for CourseContent id=" + content.getId()
                    ));

            addContentTranslation(content, contentDto, language);
        }
    }

    private void addContentTranslation(CourseContent content, CourseContentTranslateReq contentDto, Language language) {
        CourseContentTranslate contentTranslate = CourseContentTranslate.builder()
                .title(contentDto.getTitle())
                .language(language)
                .courseContent(content)
                .build();

        content.getTranslations().add(contentTranslate);
        translateLectures(content, contentDto.getCourseLectures(), language);
    }

    private void translateLectures(CourseContent content, List<CourseLectureTranslateReq> lectureDtos, Language language) {
        for (CourseLecture lecture : content.getCourseLectures()) {
            CourseLectureTranslateReq lectureDto = lectureDtos.stream()
                    .filter(ld -> ld.getId().equals(lecture.getId()))
                    .findFirst()
                    .orElseThrow(() -> new RuntimeException(
                            "Missing translation DTO for CourseLecture id=" + lecture.getId()
                    ));

            CourseLectureTranslate lectureTranslate = CourseLectureTranslate.builder()
                    .language(language)
                    .title(lectureDto.getTitle())
                    .description(lectureDto.getDescription())
                    .contentText(lectureDto.getContentText())
                    .courseLecture(lecture)
                    .build();

            lecture.getTranslations().add(lectureTranslate);
        }
    }

Pooling

Pooling претставува процес каде што не се отвара нова конекција за секој request, туку има константен број на отворени конекции кои се доделуваат на различни requests. Со ова значително се намалува времето по request бидејќи не се губи време за отварање на нова и затворање на стара конекција.

Во мојот проект ова го правам со Hikari Pool во Java Spring Boot. Hikari е автоматски вклучено во Spring Boot (не треба дополнителна конфигурација за користење) преку spring-boot-starter-web библиотеката.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>

Дополнително во application.properties фајлот за конфигурација може да се конфигурираат параметри за pooling

# Име на базенот
spring.datasource.hikari.pool-name=ShifterHikariPool
# Максимален број на конекции
spring.datasource.hikari.maximum-pool-size=20
# Минимум конекции кои секогаш ќе се спремни за да преземат нови requests
spring.datasource.hikari.minimum-idle=5
# Колку долго да се чека за конекција пред requestot да е одбиен (ако сите се зафатени)
spring.datasource.hikari.connection-timeout=30000
# Колку долго може да седи една конекција слободна (пред да биде затворена)
spring.datasource.hikari.idle-timeout=600000
# Максимално времетраење на една конекција (пред да биде заменета со нова)
spring.datasource.hikari.max-lifetime=1800000
Note: See TracWiki for help on using the wiki.