Skip to content

Commit 4430c80

Browse files
author
amvanbaren
committed
Publisher statistics
1 parent 37a929d commit 4430c80

23 files changed

+952
-141
lines changed

server/src/main/java/org/eclipse/openvsx/UserAPI.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import jakarta.servlet.http.HttpServletRequest;
1313
import org.eclipse.openvsx.eclipse.EclipseService;
1414
import org.eclipse.openvsx.entities.NamespaceMembership;
15+
import org.eclipse.openvsx.entities.PublisherStatistics;
1516
import org.eclipse.openvsx.entities.UserData;
1617
import org.eclipse.openvsx.json.*;
1718
import org.eclipse.openvsx.repositories.RepositoryService;
@@ -340,4 +341,18 @@ public ResponseEntity<UserJson> signPublisherAgreement() {
340341
}
341342
}
342343

344+
@GetMapping(
345+
path = "/user/statistics",
346+
produces = MediaType.APPLICATION_JSON_VALUE
347+
)
348+
public List<PublisherStatisticsJson> getPublisherStatistics() {
349+
var user = users.findLoggedInUser();
350+
if (user == null) {
351+
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
352+
}
353+
354+
return repositories.findPublisherStatisticsByUser(user).stream()
355+
.map(PublisherStatistics::toJson)
356+
.toList();
357+
}
343358
}

server/src/main/java/org/eclipse/openvsx/admin/AdminService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.eclipse.openvsx.migration.HandlerJobRequest;
2323
import org.eclipse.openvsx.repositories.RepositoryService;
2424
import org.eclipse.openvsx.search.SearchUtilService;
25+
import org.eclipse.openvsx.statistics.MonthlyStatisticsJobRequestHandler;
2526
import org.eclipse.openvsx.storage.StorageUtilService;
2627
import org.eclipse.openvsx.util.*;
2728
import org.jobrunr.scheduling.JobRequestScheduler;
@@ -78,7 +79,7 @@ public AdminService(
7879

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

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/** ******************************************************************************
2+
* Copyright (c) 2024 Precies. Software OU and others
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
* ****************************************************************************** */
10+
package org.eclipse.openvsx.entities;
11+
12+
import jakarta.persistence.*;
13+
import org.eclipse.openvsx.json.PublisherStatisticsJson;
14+
15+
import java.util.*;
16+
17+
@Entity
18+
@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "year", "month"})})
19+
public class PublisherStatistics {
20+
21+
@Id
22+
@GeneratedValue(generator = "publisherStatisticsSeq")
23+
@SequenceGenerator(name = "publisherStatisticsSeq", sequenceName = "publisher_statistics_seq")
24+
private long id;
25+
26+
@ManyToOne
27+
@JoinColumn(name = "user_data")
28+
private UserData user;
29+
30+
private int year;
31+
32+
private int month;
33+
34+
@ElementCollection(fetch = FetchType.EAGER)
35+
@MapKeyColumn(name = "extension_identifier")
36+
@Column(name = "downloads")
37+
private Map<String, Long> extensionDownloads;
38+
39+
@ElementCollection(fetch = FetchType.EAGER)
40+
@MapKeyColumn(name = "extension_identifier")
41+
@Column(name = "downloads")
42+
private Map<String, Long> extensionTotalDownloads;
43+
44+
public PublisherStatisticsJson toJson() {
45+
var json = new PublisherStatisticsJson();
46+
json.setYear(year);
47+
json.setMonth(month);
48+
json.setExtensionDownloads(extensionDownloads);
49+
json.setExtensionTotalDownloads(extensionTotalDownloads);
50+
return json;
51+
}
52+
53+
public long getId() {
54+
return id;
55+
}
56+
57+
public void setId(long id) {
58+
this.id = id;
59+
}
60+
61+
public UserData getUser() {
62+
return user;
63+
}
64+
65+
public void setUser(UserData user) {
66+
this.user = user;
67+
}
68+
69+
public int getYear() {
70+
return year;
71+
}
72+
73+
public void setYear(int year) {
74+
this.year = year;
75+
}
76+
77+
public int getMonth() {
78+
return month;
79+
}
80+
81+
public void setMonth(int month) {
82+
this.month = month;
83+
}
84+
85+
public Map<String, Long> getExtensionDownloads() {
86+
return extensionDownloads;
87+
}
88+
89+
public void setExtensionDownloads(Map<String, Long> extensionDownloads) {
90+
this.extensionDownloads = extensionDownloads;
91+
}
92+
93+
public Map<String, Long> getExtensionTotalDownloads() {
94+
return extensionTotalDownloads;
95+
}
96+
97+
public void setExtensionTotalDownloads(Map<String, Long> extensionTotalDownloads) {
98+
this.extensionTotalDownloads = extensionTotalDownloads;
99+
}
100+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/** ******************************************************************************
2+
* Copyright (c) 2024 Precies. Software OU and others
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
* ****************************************************************************** */
10+
package org.eclipse.openvsx.json;
11+
12+
import com.fasterxml.jackson.annotation.JsonInclude;
13+
14+
import java.util.Map;
15+
16+
@JsonInclude(JsonInclude.Include.NON_NULL)
17+
public class PublisherStatisticsJson extends ResultJson {
18+
19+
public static PublisherStatisticsJson error(String message) {
20+
var result = new PublisherStatisticsJson();
21+
result.setError(message);
22+
return result;
23+
}
24+
25+
private int year;
26+
27+
private int month;
28+
29+
private Map<String, Long> extensionDownloads;
30+
31+
private Map<String, Long> extensionTotalDownloads;
32+
33+
public int getYear() {
34+
return year;
35+
}
36+
37+
public void setYear(int year) {
38+
this.year = year;
39+
}
40+
41+
public int getMonth() {
42+
return month;
43+
}
44+
45+
public void setMonth(int month) {
46+
this.month = month;
47+
}
48+
49+
public Map<String, Long> getExtensionDownloads() {
50+
return extensionDownloads;
51+
}
52+
53+
public void setExtensionDownloads(Map<String, Long> extensionDownlaods) {
54+
this.extensionDownloads = extensionDownlaods;
55+
}
56+
57+
public Map<String, Long> getExtensionTotalDownloads() {
58+
return extensionTotalDownloads;
59+
}
60+
61+
public void setExtensionTotalDownloads(Map<String, Long> extensionTotalDownlaods) {
62+
this.extensionTotalDownloads = extensionTotalDownlaods;
63+
}
64+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/** ******************************************************************************
2+
* Copyright (c) 2024 Precies. Software OU and others
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
* ****************************************************************************** */
10+
package org.eclipse.openvsx.repositories;
11+
12+
import org.eclipse.openvsx.entities.PublisherStatistics;
13+
import org.eclipse.openvsx.entities.UserData;
14+
import org.springframework.data.repository.Repository;
15+
import org.springframework.data.util.Streamable;
16+
17+
public interface PublisherStatisticsRepository extends Repository<PublisherStatistics, Long> {
18+
19+
PublisherStatistics findByYearAndMonthAndUser(int year, int month, UserData user);
20+
21+
Streamable<PublisherStatistics> findByUser(UserData user);
22+
}

server/src/main/java/org/eclipse/openvsx/repositories/RepositoryService.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public class RepositoryService {
6161
private final MigrationItemRepository migrationItemRepo;
6262
private final SignatureKeyPairRepository signatureKeyPairRepo;
6363
private final SignatureKeyPairJooqRepository signatureKeyPairJooqRepo;
64+
private final PublisherStatisticsRepository publisherStatisticsRepo;
6465

6566
public RepositoryService(
6667
NamespaceRepository namespaceRepo,
@@ -84,7 +85,8 @@ public RepositoryService(
8485
AdminStatisticCalculationsRepository adminStatisticCalculationsRepo,
8586
MigrationItemRepository migrationItemRepo,
8687
SignatureKeyPairRepository signatureKeyPairRepo,
87-
SignatureKeyPairJooqRepository signatureKeyPairJooqRepo
88+
SignatureKeyPairJooqRepository signatureKeyPairJooqRepo,
89+
PublisherStatisticsRepository publisherStatisticsRepo
8890
) {
8991
this.namespaceRepo = namespaceRepo;
9092
this.namespaceJooqRepo = namespaceJooqRepo;
@@ -108,6 +110,7 @@ public RepositoryService(
108110
this.migrationItemRepo = migrationItemRepo;
109111
this.signatureKeyPairRepo = signatureKeyPairRepo;
110112
this.signatureKeyPairJooqRepo = signatureKeyPairJooqRepo;
113+
this.publisherStatisticsRepo = publisherStatisticsRepo;
111114
}
112115

113116
public Namespace findNamespace(String name) {
@@ -706,4 +709,16 @@ public boolean hasExtension(String namespace, String extension) {
706709
public Streamable<Extension> findDeprecatedExtensions(Extension replacement) {
707710
return extensionRepo.findByReplacement(replacement);
708711
}
712+
713+
public PublisherStatistics findPublisherStatisticsByYearAndMonthAndUser(int year, int month, UserData user) {
714+
return publisherStatisticsRepo.findByYearAndMonthAndUser(year, month, user);
715+
}
716+
717+
public Streamable<PublisherStatistics> findPublisherStatisticsByUser(UserData user) {
718+
return publisherStatisticsRepo.findByUser(user);
719+
}
720+
721+
public Streamable<UserData> findUsersByProvider(String provider) {
722+
return userDataRepo.findByProvider(provider);
723+
}
709724
}

server/src/main/java/org/eclipse/openvsx/repositories/UserDataRepository.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.springframework.data.domain.Page;
1414
import org.springframework.data.domain.Pageable;
1515
import org.springframework.data.repository.Repository;
16+
import org.springframework.data.util.Streamable;
1617

1718
public interface UserDataRepository extends Repository<UserData, Long> {
1819

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

2324
long count();
2425

26+
Streamable<UserData> findByProvider(String provider);
2527
}

server/src/main/java/org/eclipse/openvsx/admin/AdminStatisticsJobRequestHandler.java renamed to server/src/main/java/org/eclipse/openvsx/statistics/AdminStatisticsJobRequestHandler.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,28 @@
77
*
88
* SPDX-License-Identifier: EPL-2.0
99
* ****************************************************************************** */
10-
package org.eclipse.openvsx.admin;
10+
package org.eclipse.openvsx.statistics;
1111

1212
import org.eclipse.openvsx.entities.AdminStatistics;
1313
import org.eclipse.openvsx.repositories.RepositoryService;
1414
import org.jobrunr.jobs.lambdas.JobRequestHandler;
15-
import org.slf4j.Logger;
16-
import org.slf4j.LoggerFactory;
1715
import org.springframework.stereotype.Component;
1816

1917
import java.time.LocalDateTime;
2018

2119
@Component
22-
public class AdminStatisticsJobRequestHandler implements JobRequestHandler<AdminStatisticsJobRequest> {
23-
24-
private static final Logger LOGGER = LoggerFactory.getLogger(AdminStatisticsJobRequestHandler.class);
20+
public class AdminStatisticsJobRequestHandler implements JobRequestHandler<StatisticsJobRequest> {
2521

2622
private final RepositoryService repositories;
27-
private final AdminStatisticsService service;
23+
private final StatisticsService service;
2824

29-
public AdminStatisticsJobRequestHandler(RepositoryService repositories, AdminStatisticsService service) {
25+
public AdminStatisticsJobRequestHandler(RepositoryService repositories, StatisticsService service) {
3026
this.repositories = repositories;
3127
this.service = service;
3228
}
3329

3430
@Override
35-
public void run(AdminStatisticsJobRequest jobRequest) throws Exception {
31+
public void run(StatisticsJobRequest jobRequest) throws Exception {
3632
var year = jobRequest.getYear();
3733
var month = jobRequest.getMonth();
3834

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
* SPDX-License-Identifier: EPL-2.0
99
* ****************************************************************************** */
10-
package org.eclipse.openvsx.admin;
10+
package org.eclipse.openvsx.statistics;
1111

1212
import org.eclipse.openvsx.migration.HandlerJobRequest;
1313
import org.eclipse.openvsx.util.TimeUtil;
@@ -19,11 +19,11 @@
1919
import java.util.UUID;
2020

2121
@Component
22-
public class MonthlyAdminStatisticsJobRequestHandler implements JobRequestHandler<HandlerJobRequest<?>> {
22+
public class MonthlyStatisticsJobRequestHandler implements JobRequestHandler<HandlerJobRequest<?>> {
2323

2424
private final JobRequestScheduler scheduler;
2525

26-
public MonthlyAdminStatisticsJobRequestHandler(JobRequestScheduler scheduler) {
26+
public MonthlyStatisticsJobRequestHandler(JobRequestScheduler scheduler) {
2727
this.scheduler = scheduler;
2828
}
2929

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

3636
var jobIdText = "AdminStatistics::year=" + year + ",month=" + month;
3737
var jobId = UUID.nameUUIDFromBytes(jobIdText.getBytes(StandardCharsets.UTF_8));
38-
scheduler.enqueue(jobId, new AdminStatisticsJobRequest(year, month));
38+
scheduler.enqueue(jobId, new StatisticsJobRequest<>(AdminStatisticsJobRequestHandler.class, year, month));
39+
40+
jobIdText = "PublisherStatistics::year=" + year + ",month=" + month;
41+
jobId = UUID.nameUUIDFromBytes(jobIdText.getBytes(StandardCharsets.UTF_8));
42+
scheduler.enqueue(jobId, new StatisticsJobRequest<>(PublisherStatisticsJobRequestHandler.class, year, month));
3943
}
4044
}

0 commit comments

Comments
 (0)