первая вресия смарт уведомлений

This commit is contained in:
upagge 2020-10-11 18:33:03 +03:00
parent e1c9436a14
commit 0d5fc08c1f
No known key found for this signature in database
GPG Key ID: 15CD012E46F6BA34
8 changed files with 159 additions and 10 deletions

View File

@ -11,5 +11,6 @@
<include file="liquibase/v.2.0.0/2020-10-02-add-column-status-teamcity.xml"/>
<include file="liquibase/v.2.0.0/2020-10-07-add-colum-reviewer-date.xml"/>
<include file="liquibase/v.2.0.0/2020-10-11-teamcity-refactoring.xml"/>
<include file="liquibase/v.2.0.0/2020-10-11-new-colum-reviewer.xml"/>
</databaseChangeLog>

View File

@ -0,0 +1,12 @@
<databaseChangeLog
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet id="2020-10-11-add-column-reviewer" author="upagge">
<addColumn tableName="reviewer">
<column name="date_smart_notify" type="datetime"/>
</addColumn>
</changeSet>
</databaseChangeLog>

View File

@ -56,6 +56,9 @@ public class Reviewer {
@Column(name = "date_change")
private LocalDateTime dateChange;
@Column(name = "date_smart_notify")
private LocalDateTime dateSmartNotify;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.REFRESH, optional = false)
@JoinColumn(name = "pull_request_id")
private PullRequest pullRequest;

View File

@ -0,0 +1,32 @@
package org.sadtech.bot.vcs.core.domain.notify.pullrequest;
import lombok.Builder;
import lombok.Getter;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
import java.util.Set;
/**
* // TODO: 11.10.2020 Добавить описание.
*
* @author upagge 11.10.2020
*/
@Getter
public class ForgottenSmartPrNotify extends PrNotify {
@Builder
protected ForgottenSmartPrNotify(Set<String> recipients, String title, String url) {
super(recipients, title, url);
}
@Override
public String generateMessage() {
return MessageFormat.format(
"{0} *Напоминание о просмотре PullRequest*" +
"{3}[{1}]({2})",
Smile.SMART, title, url, Smile.HR
);
}
}

View File

@ -0,0 +1,38 @@
package org.sadtech.bot.vcs.core.domain.notify.pullrequest;
import lombok.Builder;
import lombok.Getter;
import org.sadtech.bot.vcs.core.domain.entity.Reviewer;
import org.sadtech.bot.vcs.core.utils.Smile;
import java.text.MessageFormat;
import java.util.Set;
/**
* // TODO: 11.10.2020 Добавить описание.
*
* @author upagge 11.10.2020
*/
@Getter
public class SmartPrNotify extends PrNotify {
private final Reviewer reviewerTriggered;
@Builder
protected SmartPrNotify(Set<String> recipients, String title, String url, Reviewer reviewerTriggered) {
super(recipients, title, url);
this.reviewerTriggered = reviewerTriggered;
}
@Override
public String generateMessage() {
return MessageFormat.format(
"{0} *Напоминание о просмотре PullRequest*\n" +
"{3}[{1}]({2})" +
"{3}" +
"{4} изменил свое решение на {5}\n\n",
Smile.SMART, title, url, Smile.HR, reviewerTriggered.getPersonLogin(), reviewerTriggered.getStatus().getValue()
);
}
}

View File

@ -26,7 +26,7 @@ public class UpdatePrNotify extends PrNotify {
@Override
public String generateMessage() {
return MessageFormat.format(
"{0} *Обновление Pull Request*\n" +
"{0} *Обновление PullRequest*\n" +
"[{1}]({2})" +
"{3}" +
"{4}: {5}\n\n",

View File

@ -18,8 +18,10 @@ import org.sadtech.bot.vcs.core.domain.entity.PullRequest_;
import org.sadtech.bot.vcs.core.domain.entity.Reviewer;
import org.sadtech.bot.vcs.core.domain.filter.PullRequestFilter;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.ConflictPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.ForgottenSmartPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.NewPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.ReviewersPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.SmartPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.StatusPrNotify;
import org.sadtech.bot.vcs.core.domain.notify.pullrequest.UpdatePrNotify;
import org.sadtech.bot.vcs.core.domain.util.ReviewerChange;
@ -93,30 +95,58 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
public PullRequest update(@NonNull PullRequest pullRequest) {
final PullRequest oldPullRequest = findAndFillId(pullRequest);
oldPullRequest.setBitbucketVersion(pullRequest.getBitbucketVersion());
forgottenNotification(oldPullRequest);
oldPullRequest.setTitle(pullRequest.getTitle());
oldPullRequest.setDescription(pullRequest.getDescription());
updateReviewers(oldPullRequest, pullRequest);
oldPullRequest.setUpdateDate(pullRequest.getUpdateDate());
updateBitbucketVersion(oldPullRequest, pullRequest);
updateStatus(oldPullRequest, pullRequest);
updateConflict(oldPullRequest, pullRequest);
final PullRequest newPullRequest = pullRequestsRepository.save(oldPullRequest);
if (!pullRequest.getBitbucketVersion().equals(newPullRequest.getBitbucketVersion())) {
return pullRequestsRepository.save(oldPullRequest);
}
private void forgottenNotification(PullRequest pullRequest) {
if (LocalDateTime.now().isAfter(pullRequest.getUpdateDate().plusHours(2L))) {
final Set<String> smartReviewers = pullRequest.getReviewers().stream()
.filter(
reviewer -> ReviewerStatus.NEEDS_WORK.equals(reviewer.getStatus())
&& LocalDateTime.now().isAfter(reviewer.getDateChange().plusHours(2L))
&& reviewer.getDateSmartNotify() == null
)
.peek(reviewer -> reviewer.setDateSmartNotify(LocalDateTime.now()))
.map(Reviewer::getPersonLogin)
.collect(Collectors.toSet());
if (!smartReviewers.isEmpty()) {
notifyService.send(
ForgottenSmartPrNotify.builder()
.recipients(smartReviewers)
.title(pullRequest.getTitle())
.url(pullRequest.getUrl())
.build()
);
}
}
}
private void updateBitbucketVersion(PullRequest oldPullRequest, PullRequest pullRequest) {
if (!oldPullRequest.getBitbucketVersion().equals(pullRequest.getBitbucketVersion())) {
oldPullRequest.setBitbucketVersion(pullRequest.getBitbucketVersion());
notifyService.send(
UpdatePrNotify.builder()
.author(oldPullRequest.getAuthorLogin())
.name(newPullRequest.getTitle())
.name(pullRequest.getTitle())
.recipients(
newPullRequest.getReviewers().stream()
pullRequest.getReviewers().stream()
.map(Reviewer::getPersonLogin)
.collect(Collectors.toSet())
)
.url(newPullRequest.getUrl())
.url(oldPullRequest.getUrl())
.build()
);
}
return newPullRequest;
}
private void updateConflict(PullRequest oldPullRequest, PullRequest pullRequest) {
@ -180,10 +210,12 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
reviewerChanges.add(ReviewerChange.ofOld(oldReviewer.getPersonLogin(), oldStatus, newStatus));
oldReviewer.setStatus(newStatus);
oldReviewer.setDateChange(LocalDateTime.now());
smartNotifyAfterReviewerDecision(newReviewer, oldPullRequest);
}
} else {
reviewerChanges.add(ReviewerChange.ofNew(newReviewer.getPersonLogin(), newReviewer.getStatus()));
newReviewer.setPullRequest(oldPullRequest);
newReviewer.setDateChange(LocalDateTime.now());
oldPullRequest.getReviewers().add(newReviewer);
}
}
@ -209,6 +241,36 @@ public class PullRequestsServiceImpl extends AbstractSimpleManagerService<PullRe
}
}
/**
* Умное уведомление ревьюверов, после того, как кто-то изменил свое решение.
*/
private void smartNotifyAfterReviewerDecision(Reviewer newReviewer, PullRequest oldPullRequest) {
final ReviewerStatus newStatus = newReviewer.getStatus();
if (!ReviewerStatus.NEEDS_WORK.equals(newStatus) && enoughTimHasPassedSinceUpdatePr(oldPullRequest.getUpdateDate())) {
final List<Reviewer> smartReviewers = oldPullRequest.getReviewers().stream()
.filter(reviewer -> LocalDateTime.now().isAfter(reviewer.getDateChange().plusHours(2L)))
.collect(Collectors.toList());
if (!smartReviewers.isEmpty()) {
notifyService.send(
SmartPrNotify.builder()
.reviewerTriggered(newReviewer)
.title(oldPullRequest.getTitle())
.url(oldPullRequest.getUrl())
.recipients(
smartReviewers.stream()
.map(Reviewer::getPersonLogin)
.collect(Collectors.toSet())
)
.build()
);
}
}
}
private boolean enoughTimHasPassedSinceUpdatePr(LocalDateTime updateDate) {
return LocalDateTime.now().isAfter(updateDate.plusHours(4L));
}
@NonNull
@Override
public List<PullRequest> getAllByReviewerAndStatuses(String login, ReviewerStatus reviewerStatus, Set<PullRequestStatus> statuses) {

View File

@ -38,7 +38,8 @@ public enum Smile {
HR("\n -- -- -- -- --\n"),
FAILURE(""),
SUCCESS(""),
BUILD("♻️");
BUILD("♻️"),
SMART("\uD83E\uDDE0");
@Getter
private final String value;