blob: 90eec70175251ef66f91ddbcb1787dddb3bbdd61 [file] [log] [blame]
package build.bazel.dashboard.github.issuestatus;
import static java.util.Objects.requireNonNull;
import com.google.common.collect.ImmutableList;
import io.r2dbc.spi.Readable;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.Maybe;
import java.time.Instant;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.stereotype.Repository;
import reactor.adapter.rxjava.RxJava3Adapter;
import reactor.core.publisher.Mono;
@Repository
@RequiredArgsConstructor
public class GithubIssueStatusRepoPg implements GithubIssueStatusRepo {
private final DatabaseClient databaseClient;
@Override
public void save(GithubIssueStatus status) {
Deque<String> actionOwners = new ArrayDeque<>(status.getActionOwners());
String actionOwner = null;
if (!actionOwners.isEmpty()) {
actionOwner = actionOwners.removeFirst();
}
DatabaseClient.GenericExecuteSpec spec =
databaseClient
.sql(
"INSERT INTO github_issue_status (owner, repo, issue_number, status, action_owner,"
+ " more_action_owners, updated_at, expected_respond_at, last_notified_at,"
+ " next_notify_at, checked_at) VALUES (:owner, :repo, :issue_number, :status,"
+ " :action_owner, :more_action_owners, :updated_at, :expected_respond_at,"
+ " :last_notified_at, :next_notify_at, :checked_at) ON CONFLICT (owner, repo,"
+ " issue_number) DO UPDATE SET status = excluded.status, action_owner ="
+ " excluded.action_owner, more_action_owners = excluded.more_action_owners,"
+ " updated_at = excluded.updated_at, expected_respond_at ="
+ " excluded.expected_respond_at, last_notified_at = excluded.last_notified_at,"
+ " next_notify_at = excluded.next_notify_at, checked_at = excluded.checked_at")
.bind("owner", status.getOwner())
.bind("repo", status.getRepo())
.bind("issue_number", status.getIssueNumber())
.bind("more_action_owners", actionOwners.toArray(new String[0]))
.bind("status", status.getStatus().toString())
.bind("updated_at", status.getUpdatedAt())
.bind("checked_at", status.getCheckedAt());
if (actionOwner != null) {
spec = spec.bind("action_owner", actionOwner);
} else {
spec = spec.bindNull("action_owner", String.class);
}
if (status.getExpectedRespondAt() != null) {
spec = spec.bind("expected_respond_at", status.getExpectedRespondAt());
} else {
spec = spec.bindNull("expected_respond_at", Instant.class);
}
if (status.getLastNotifiedAt() != null) {
spec = spec.bind("last_notified_at", status.getLastNotifiedAt());
} else {
spec = spec.bindNull("last_notified_at", Instant.class);
}
if (status.getNextNotifyAt() != null) {
spec = spec.bind("next_notify_at", status.getNextNotifyAt());
} else {
spec = spec.bindNull("next_notify_at", Instant.class);
}
spec.then().block();
}
@Override
public Optional<GithubIssueStatus> findOne(String owner, String repo, int issueNumber) {
return Optional.ofNullable(
databaseClient
.sql(
"SELECT owner, repo, issue_number, status, action_owner, more_action_owners,"
+ " updated_at, expected_respond_at, last_notified_at, next_notify_at,"
+ " checked_at FROM github_issue_status WHERE owner = :owner AND repo = :repo"
+ " AND issue_number = :issue_number")
.bind("owner", owner)
.bind("repo", repo)
.bind("issue_number", issueNumber)
.map(this::toGithubIssueStatus)
.one()
.block());
}
private GithubIssueStatus toGithubIssueStatus(Readable row) {
ImmutableList.Builder<String> actionOwners = new ImmutableList.Builder<>();
String actionOwner = row.get("action_owner", String.class);
if (actionOwner != null && !actionOwner.isBlank()) {
actionOwners.add(actionOwner);
}
actionOwners.add(requireNonNull(row.get("more_action_owners", String[].class)));
return GithubIssueStatus.builder()
.owner(requireNonNull(row.get("owner", String.class)))
.repo(requireNonNull(row.get("repo", String.class)))
.issueNumber(requireNonNull(row.get("issue_number", Integer.class)))
.status(GithubIssueStatus.Status.valueOf(row.get("status", String.class)))
.actionOwners(actionOwners.build())
.updatedAt(requireNonNull(row.get("updated_at", Instant.class)))
.expectedRespondAt(row.get("expected_respond_at", Instant.class))
.lastNotifiedAt(row.get("last_notified_at", Instant.class))
.nextNotifyAt(row.get("next_notify_at", Instant.class))
.checkedAt(requireNonNull(row.get("checked_at", Instant.class)))
.build();
}
}