Skip to content

Commit

Permalink
Publisher statistics
Browse files Browse the repository at this point in the history
  • Loading branch information
amvanbaren committed Jan 17, 2025
1 parent 37a929d commit 4430c80
Show file tree
Hide file tree
Showing 23 changed files with 952 additions and 141 deletions.
15 changes: 15 additions & 0 deletions server/src/main/java/org/eclipse/openvsx/UserAPI.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import jakarta.servlet.http.HttpServletRequest;
import org.eclipse.openvsx.eclipse.EclipseService;
import org.eclipse.openvsx.entities.NamespaceMembership;
import org.eclipse.openvsx.entities.PublisherStatistics;
import org.eclipse.openvsx.entities.UserData;
import org.eclipse.openvsx.json.*;
import org.eclipse.openvsx.repositories.RepositoryService;
Expand Down Expand Up @@ -340,4 +341,18 @@ public ResponseEntity<UserJson> signPublisherAgreement() {
}
}

@GetMapping(
path = "/user/statistics",
produces = MediaType.APPLICATION_JSON_VALUE
)
public List<PublisherStatisticsJson> getPublisherStatistics() {
var user = users.findLoggedInUser();
if (user == null) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}

return repositories.findPublisherStatisticsByUser(user).stream()
.map(PublisherStatistics::toJson)
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.eclipse.openvsx.migration.HandlerJobRequest;
import org.eclipse.openvsx.repositories.RepositoryService;
import org.eclipse.openvsx.search.SearchUtilService;
import org.eclipse.openvsx.statistics.MonthlyStatisticsJobRequestHandler;
import org.eclipse.openvsx.storage.StorageUtilService;
import org.eclipse.openvsx.util.*;
import org.jobrunr.scheduling.JobRequestScheduler;
Expand Down Expand Up @@ -78,7 +79,7 @@ public AdminService(

@EventListener
public void applicationStarted(ApplicationStartedEvent event) {
var jobRequest = new HandlerJobRequest<>(MonthlyAdminStatisticsJobRequestHandler.class);
var jobRequest = new HandlerJobRequest<>(MonthlyStatisticsJobRequestHandler.class);
scheduler.scheduleRecurrently("MonthlyAdminStatistics", Cron.monthly(1, 0, 3), ZoneId.of("UTC"), jobRequest);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/** ******************************************************************************
* Copyright (c) 2024 Precies. Software OU and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
* ****************************************************************************** */
package org.eclipse.openvsx.entities;

import jakarta.persistence.*;
import org.eclipse.openvsx.json.PublisherStatisticsJson;

import java.util.*;

@Entity
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "year", "month"})})
public class PublisherStatistics {

@Id
@GeneratedValue(generator = "publisherStatisticsSeq")
@SequenceGenerator(name = "publisherStatisticsSeq", sequenceName = "publisher_statistics_seq")
private long id;

@ManyToOne
@JoinColumn(name = "user_data")
private UserData user;

private int year;

private int month;

@ElementCollection(fetch = FetchType.EAGER)
@MapKeyColumn(name = "extension_identifier")
@Column(name = "downloads")
private Map<String, Long> extensionDownloads;

@ElementCollection(fetch = FetchType.EAGER)
@MapKeyColumn(name = "extension_identifier")
@Column(name = "downloads")
private Map<String, Long> extensionTotalDownloads;

public PublisherStatisticsJson toJson() {
var json = new PublisherStatisticsJson();
json.setYear(year);
json.setMonth(month);
json.setExtensionDownloads(extensionDownloads);
json.setExtensionTotalDownloads(extensionTotalDownloads);
return json;
}

public long getId() {
return id;
}

public void setId(long id) {
this.id = id;
}

public UserData getUser() {
return user;
}

public void setUser(UserData user) {
this.user = user;
}

public int getYear() {
return year;
}

public void setYear(int year) {
this.year = year;
}

public int getMonth() {
return month;
}

public void setMonth(int month) {
this.month = month;
}

public Map<String, Long> getExtensionDownloads() {
return extensionDownloads;
}

public void setExtensionDownloads(Map<String, Long> extensionDownloads) {
this.extensionDownloads = extensionDownloads;
}

public Map<String, Long> getExtensionTotalDownloads() {
return extensionTotalDownloads;
}

public void setExtensionTotalDownloads(Map<String, Long> extensionTotalDownloads) {
this.extensionTotalDownloads = extensionTotalDownloads;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/** ******************************************************************************
* Copyright (c) 2024 Precies. Software OU and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
* ****************************************************************************** */
package org.eclipse.openvsx.json;

import com.fasterxml.jackson.annotation.JsonInclude;

import java.util.Map;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class PublisherStatisticsJson extends ResultJson {

public static PublisherStatisticsJson error(String message) {
var result = new PublisherStatisticsJson();
result.setError(message);
return result;
}

private int year;

private int month;

private Map<String, Long> extensionDownloads;

private Map<String, Long> extensionTotalDownloads;

public int getYear() {
return year;
}

public void setYear(int year) {
this.year = year;
}

public int getMonth() {
return month;
}

public void setMonth(int month) {
this.month = month;
}

public Map<String, Long> getExtensionDownloads() {
return extensionDownloads;
}

public void setExtensionDownloads(Map<String, Long> extensionDownlaods) {
this.extensionDownloads = extensionDownlaods;
}

public Map<String, Long> getExtensionTotalDownloads() {
return extensionTotalDownloads;
}

public void setExtensionTotalDownloads(Map<String, Long> extensionTotalDownlaods) {
this.extensionTotalDownloads = extensionTotalDownlaods;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/** ******************************************************************************
* Copyright (c) 2024 Precies. Software OU and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
* ****************************************************************************** */
package org.eclipse.openvsx.repositories;

import org.eclipse.openvsx.entities.PublisherStatistics;
import org.eclipse.openvsx.entities.UserData;
import org.springframework.data.repository.Repository;
import org.springframework.data.util.Streamable;

public interface PublisherStatisticsRepository extends Repository<PublisherStatistics, Long> {

PublisherStatistics findByYearAndMonthAndUser(int year, int month, UserData user);

Streamable<PublisherStatistics> findByUser(UserData user);
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class RepositoryService {
private final MigrationItemRepository migrationItemRepo;
private final SignatureKeyPairRepository signatureKeyPairRepo;
private final SignatureKeyPairJooqRepository signatureKeyPairJooqRepo;
private final PublisherStatisticsRepository publisherStatisticsRepo;

public RepositoryService(
NamespaceRepository namespaceRepo,
Expand All @@ -84,7 +85,8 @@ public RepositoryService(
AdminStatisticCalculationsRepository adminStatisticCalculationsRepo,
MigrationItemRepository migrationItemRepo,
SignatureKeyPairRepository signatureKeyPairRepo,
SignatureKeyPairJooqRepository signatureKeyPairJooqRepo
SignatureKeyPairJooqRepository signatureKeyPairJooqRepo,
PublisherStatisticsRepository publisherStatisticsRepo
) {
this.namespaceRepo = namespaceRepo;
this.namespaceJooqRepo = namespaceJooqRepo;
Expand All @@ -108,6 +110,7 @@ public RepositoryService(
this.migrationItemRepo = migrationItemRepo;
this.signatureKeyPairRepo = signatureKeyPairRepo;
this.signatureKeyPairJooqRepo = signatureKeyPairJooqRepo;
this.publisherStatisticsRepo = publisherStatisticsRepo;
}

public Namespace findNamespace(String name) {
Expand Down Expand Up @@ -706,4 +709,16 @@ public boolean hasExtension(String namespace, String extension) {
public Streamable<Extension> findDeprecatedExtensions(Extension replacement) {
return extensionRepo.findByReplacement(replacement);
}

public PublisherStatistics findPublisherStatisticsByYearAndMonthAndUser(int year, int month, UserData user) {
return publisherStatisticsRepo.findByYearAndMonthAndUser(year, month, user);
}

public Streamable<PublisherStatistics> findPublisherStatisticsByUser(UserData user) {
return publisherStatisticsRepo.findByUser(user);
}

public Streamable<UserData> findUsersByProvider(String provider) {
return userDataRepo.findByProvider(provider);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.Repository;
import org.springframework.data.util.Streamable;

public interface UserDataRepository extends Repository<UserData, Long> {

Expand All @@ -22,4 +23,5 @@ public interface UserDataRepository extends Repository<UserData, Long> {

long count();

Streamable<UserData> findByProvider(String provider);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,28 @@
*
* SPDX-License-Identifier: EPL-2.0
* ****************************************************************************** */
package org.eclipse.openvsx.admin;
package org.eclipse.openvsx.statistics;

import org.eclipse.openvsx.entities.AdminStatistics;
import org.eclipse.openvsx.repositories.RepositoryService;
import org.jobrunr.jobs.lambdas.JobRequestHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

@Component
public class AdminStatisticsJobRequestHandler implements JobRequestHandler<AdminStatisticsJobRequest> {

private static final Logger LOGGER = LoggerFactory.getLogger(AdminStatisticsJobRequestHandler.class);
public class AdminStatisticsJobRequestHandler implements JobRequestHandler<StatisticsJobRequest> {

private final RepositoryService repositories;
private final AdminStatisticsService service;
private final StatisticsService service;

public AdminStatisticsJobRequestHandler(RepositoryService repositories, AdminStatisticsService service) {
public AdminStatisticsJobRequestHandler(RepositoryService repositories, StatisticsService service) {
this.repositories = repositories;
this.service = service;
}

@Override
public void run(AdminStatisticsJobRequest jobRequest) throws Exception {
public void run(StatisticsJobRequest jobRequest) throws Exception {
var year = jobRequest.getYear();
var month = jobRequest.getMonth();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*
* SPDX-License-Identifier: EPL-2.0
* ****************************************************************************** */
package org.eclipse.openvsx.admin;
package org.eclipse.openvsx.statistics;

import org.eclipse.openvsx.migration.HandlerJobRequest;
import org.eclipse.openvsx.util.TimeUtil;
Expand All @@ -19,11 +19,11 @@
import java.util.UUID;

@Component
public class MonthlyAdminStatisticsJobRequestHandler implements JobRequestHandler<HandlerJobRequest<?>> {
public class MonthlyStatisticsJobRequestHandler implements JobRequestHandler<HandlerJobRequest<?>> {

private final JobRequestScheduler scheduler;

public MonthlyAdminStatisticsJobRequestHandler(JobRequestScheduler scheduler) {
public MonthlyStatisticsJobRequestHandler(JobRequestScheduler scheduler) {
this.scheduler = scheduler;
}

Expand All @@ -35,6 +35,10 @@ public void run(HandlerJobRequest<?> jobRequest) throws Exception {

var jobIdText = "AdminStatistics::year=" + year + ",month=" + month;
var jobId = UUID.nameUUIDFromBytes(jobIdText.getBytes(StandardCharsets.UTF_8));
scheduler.enqueue(jobId, new AdminStatisticsJobRequest(year, month));
scheduler.enqueue(jobId, new StatisticsJobRequest<>(AdminStatisticsJobRequestHandler.class, year, month));

jobIdText = "PublisherStatistics::year=" + year + ",month=" + month;
jobId = UUID.nameUUIDFromBytes(jobIdText.getBytes(StandardCharsets.UTF_8));
scheduler.enqueue(jobId, new StatisticsJobRequest<>(PublisherStatisticsJobRequestHandler.class, year, month));
}
}
Loading

0 comments on commit 4430c80

Please sign in to comment.