Skip to content

Commit

Permalink
Merge branch 'release/0.0.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
johnnymillergh committed Aug 18, 2021
2 parents 8fa2d5a + 9a8438a commit a976f19
Show file tree
Hide file tree
Showing 54 changed files with 685 additions and 476 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ ij_javascript_while_on_new_line = false
ij_javascript_wrap_comments = false

[{*.markdown,*.md}]
max_line_length = unset
ij_markdown_force_one_space_after_blockquote_symbol = true
ij_markdown_force_one_space_after_header_symbol = true
ij_markdown_force_one_space_after_list_bullet = true
Expand Down
113 changes: 51 additions & 62 deletions CHANGELOG.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ Here is the highlights of **Muscle and Fitness Server**:

4. Secured API. [RBAC](https://en.wikipedia.org/wiki/Role-based_access_control) by API gateway and Auth Center. JWT authentication, and RBAC authorization.

5. [MySQL Replication for High Availability](https://severalnines.com/resources/database-management-tutorials/mysql-replication-high-availability-tutorial). Multi data source. Dynamic SQL read-write isolation. MyBatis-Plus is the integrated ORM library.
5. [MySQL Replication for High Availability](https://severalnines.com/resources/database-management-tutorials/mysql-replication-high-availability-tutorial). Multi data source. [Dynamic SQL read-write isolation](https://baomidou.com/guide/dynamic-datasource.html). MyBatis-Plus is the integrated ORM library.

6. Redis 6.x support. [Master-slave replication for high availability](https://redis.io/topics/replication). Redis cluster

7. Docker, Rancher Kubernetes support. Google JIB for building Docker container images.

8. OSS service, based on [Minio](https://min.io/) and SFTP integration. Asynchronous [Progressive Download](https://www.nginx.com/resources/glossary/progressive-download/) resources. The media player will play back that content using sequential byte-range requests. Refers to [a request for partial content](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests) (HTTP 206). This type of request is typically used to retrieve a large asset in smaller segments. This technique is employed by HTTP Progressive Download to avoid long buffering times.
8. OSS service, based on [Minio](https://min.io/) and SFTP integration. Asynchronous [Progressive Download](https://www.nginx.com/resources/glossary/progressive-download/) resources. Chunked resource upload. The media player will play back that content using sequential byte-range requests. Refers to [a request for partial content](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests) (HTTP 206). This type of request is typically used to retrieve a large asset in smaller segments. This technique is employed by HTTP Progressive Download to avoid long buffering times.

9. [STOMP over WebSocket](https://www.toptal.com/java/stomp-spring-boot-websocket) (SockJS), real time messaging, based on [RabbitMQ STOMP](https://www.rabbitmq.com/stomp.html) message broker.

Expand Down
4 changes: 2 additions & 2 deletions api-gateway/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<parent>
<groupId>com.jmsoftware.maf</groupId>
<artifactId>muscle-and-fitness-server</artifactId>
<version>0.0.3</version>
<version>0.0.4</version>
</parent>

<!-- Build Settings -->
Expand All @@ -33,7 +33,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.14.0</version>
<version>${maven-pmd-plugin.version}</version>
<configuration>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<targetJdk>${java.version}</targetJdk>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public RouterFunction<ServerResponse> doc() {
public RouterFunction<ServerResponse> favicon() {
return route(GET("/favicon.ico"), request -> {
log.info("Redirect to favicon.");
return ServerResponse.temporaryRedirect(URI.create("/static/icon/favicon.ico")).build();
return ServerResponse.temporaryRedirect(URI.create("/static/asset/favicon.ico")).build();
});
}
}
4 changes: 2 additions & 2 deletions auth-center/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<parent>
<groupId>com.jmsoftware.maf</groupId>
<artifactId>muscle-and-fitness-server</artifactId>
<version>0.0.3</version>
<version>0.0.4</version>
</parent>

<!-- Build Settings -->
Expand All @@ -33,7 +33,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.14.0</version>
<version>${maven-pmd-plugin.version}</version>
<configuration>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<targetJdk>${java.version}</targetJdk>
Expand Down
2 changes: 1 addition & 1 deletion auth-center/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ spring:
multipart:
# `location` specifies the directory where uploaded files will be stored. When not specified,
# a temporary directory will be used. ATTENTION: it may differ due to OS.
location: ~/Documents/@project.parent.artifactId@/${spring.application.name}/temprary-file
location: @project.parent.artifactId@/${spring.application.name}/temprary-file
# `max-file-size` specifies the maximum size permitted for uploaded files. The default is 1MB. We set it as 64 MB.
max-file-size: 64MB
# `max-request-size` specifies the maximum size allowed for multipart/form-data requests. The default is 10MB.
Expand Down
2 changes: 1 addition & 1 deletion common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<parent>
<groupId>com.jmsoftware.maf</groupId>
<artifactId>muscle-and-fitness-server</artifactId>
<version>0.0.3</version>
<version>0.0.4</version>
</parent>

<!-- Scoped Dependencies Management -->
Expand Down
4 changes: 2 additions & 2 deletions maf-mis/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
<parent>
<groupId>com.jmsoftware.maf</groupId>
<artifactId>muscle-and-fitness-server</artifactId>
<version>0.0.3</version>
<version>0.0.4</version>
</parent>

<!-- Build Settings -->
Expand All @@ -33,7 +33,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.14.0</version>
<version>${maven-pmd-plugin.version}</version>
<configuration>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<targetJdk>${java.version}</targetJdk>
Expand Down
2 changes: 1 addition & 1 deletion maf-mis/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ spring:
multipart:
# `location` specifies the directory where uploaded files will be stored. When not specified,
# a temporary directory will be used. ATTENTION: it may differ due to OS.
location: ~/Documents/@project.parent.artifactId@/${spring.application.name}/temprary-file
location: @project.parent.artifactId@/${spring.application.name}/temprary-file
# `max-file-size` specifies the maximum size permitted for uploaded files. The default is 1MB. We set it as 64 MB.
max-file-size: 64MB
# `max-request-size` specifies the maximum size allowed for multipart/form-data requests. The default is 10MB.
Expand Down
6 changes: 3 additions & 3 deletions oss-center/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
<!-- Sub-module Basics -->
<artifactId>oss-center</artifactId>
<name>Muscle and Fitness Server :: OSS Center</name>
<description>Object Storage Service (OOS) Center for M&amp;F.</description>
<description>Object Storage Service (OSS) Center for M&amp;F.</description>
<parent>
<groupId>com.jmsoftware.maf</groupId>
<artifactId>muscle-and-fitness-server</artifactId>
<version>0.0.3</version>
<version>0.0.4</version>
</parent>

<!-- Build Settings -->
Expand All @@ -33,7 +33,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>3.14.0</version>
<version>${maven-pmd-plugin.version}</version>
<configuration>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<targetJdk>${java.version}</targetJdk>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.jmsoftware.maf.osscenter.read.controller;

import com.jmsoftware.maf.common.bean.ResponseBodyBean;
import com.jmsoftware.maf.osscenter.read.entity.SerializableStatObjectResponse;
import com.jmsoftware.maf.osscenter.read.service.ReadResourceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
Expand Down Expand Up @@ -42,4 +44,11 @@ public ResponseEntity<StreamingResponseBody> downloadSingleResource(@PathVariabl
@PathVariable String object) {
return this.readResourceService.asyncDownloadSingleResource(bucket, object);
}

@GetMapping("/stat/{bucket}/{object}")
@ApiOperation(value = "Get the information of single resource", notes = "Get the information of single resource")
public ResponseBodyBean<SerializableStatObjectResponse> statSingleResource(@PathVariable String bucket,
@PathVariable String object) {
return ResponseBodyBean.ofSuccess(this.readResourceService.stateObject(bucket, object));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.jmsoftware.maf.osscenter.read.entity;

import lombok.AccessLevel;
import lombok.Data;
import lombok.Setter;

import java.util.List;
import java.util.Map;

/**
* Description: SerializableGenericResponse, change description here.
*
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com, date: 8/12/2021 5:07 PM
**/
@Data
@Setter(AccessLevel.PROTECTED)
public class SerializableGenericResponse {
private Map<String, List<String>> headers;
private String bucket;
private String region;
private String object;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.jmsoftware.maf.osscenter.read.entity;

import io.minio.StatObjectResponse;
import io.minio.messages.LegalHold;
import io.minio.messages.RetentionMode;
import lombok.*;

import java.time.ZonedDateTime;
import java.util.Map;

/**
* Description: SerializableStatObjectResponse, change description here.
*
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com, date: 8/12/2021 5:04 PM
**/
@Data
@Setter(AccessLevel.NONE)
@EqualsAndHashCode(callSuper = true)
public class SerializableStatObjectResponse extends SerializableGenericResponse {
private String etag;
private long size;
private ZonedDateTime lastModified;
private RetentionMode retentionMode;
private ZonedDateTime retentionRetainUntilDate;
private LegalHold legalHold;
private boolean deleteMarker;
private Map<String, String> userMetadata;

public static SerializableStatObjectResponse build(StatObjectResponse statObjectResponse) {
val serializableStatObjectResponse = new SerializableStatObjectResponse();
serializableStatObjectResponse.setHeaders(statObjectResponse.headers().toMultimap());
serializableStatObjectResponse.setBucket(statObjectResponse.bucket());
serializableStatObjectResponse.setRegion(statObjectResponse.region());
serializableStatObjectResponse.setObject(statObjectResponse.object());
serializableStatObjectResponse.etag = statObjectResponse.etag();
serializableStatObjectResponse.size = statObjectResponse.size();
serializableStatObjectResponse.lastModified = statObjectResponse.lastModified();
serializableStatObjectResponse.retentionMode = statObjectResponse.retentionMode();
serializableStatObjectResponse.retentionRetainUntilDate = statObjectResponse.retentionRetainUntilDate();
serializableStatObjectResponse.legalHold = statObjectResponse.legalHold();
serializableStatObjectResponse.deleteMarker = statObjectResponse.deleteMarker();
serializableStatObjectResponse.userMetadata = statObjectResponse.userMetadata();
return serializableStatObjectResponse;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.jmsoftware.maf.osscenter.read.service;

import com.jmsoftware.maf.osscenter.read.entity.SerializableStatObjectResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.util.unit.DataSize;
Expand All @@ -18,6 +19,7 @@
@Validated
public interface ReadResourceService {
String BUCKET_OBJECT_NAME_REGEX = "^.+/.+$";
DataSize TINY_CHUNK_SIZE = DataSize.ofBytes(512);
DataSize SMALL_CHUNK_SIZE = DataSize.ofMegabytes(1);
DataSize MEDIUM_CHUNK_SIZE = DataSize.ofMegabytes(4);
DataSize LARGE_CHUNK_SIZE = DataSize.ofMegabytes(8);
Expand All @@ -41,4 +43,13 @@ ResponseEntity<StreamingResponseBody> asyncStreamSingleResource(@NotBlank String
* @return the response entity
*/
ResponseEntity<StreamingResponseBody> asyncDownloadSingleResource(@NotBlank String bucket, @NotBlank String object);

/**
* Gets resource information.
*
* @param bucket the bucket
* @param object the object
* @return the resource detail
*/
SerializableStatObjectResponse stateObject(@NotBlank String bucket, @NotBlank String object);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.IoUtil;
import com.jmsoftware.maf.osscenter.read.entity.SerializableStatObjectResponse;
import com.jmsoftware.maf.osscenter.read.service.ReadResourceService;
import com.jmsoftware.maf.springcloudstarter.helper.MinioHelper;
import com.jmsoftware.maf.springcloudstarter.minio.MinioHelper;
import io.minio.StatObjectResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -42,7 +43,7 @@ public ResponseEntity<StreamingResponseBody> asyncStreamSingleResource(@NotBlank
}
val httpRanges = HttpRange.parseRanges(range);
if (CollUtil.isEmpty(httpRanges)) {
val getObjectResponse = this.minioHelper.getObject(bucket, object, 0, MEDIUM_CHUNK_SIZE.toBytes());
val getObjectResponse = this.minioHelper.getObject(bucket, object, 0, TINY_CHUNK_SIZE.toBytes());
return ResponseEntity.ok()
.header(HttpHeaders.ACCEPT_RANGES, "bytes")
.contentLength(statObjectResponse.size())
Expand Down Expand Up @@ -79,14 +80,19 @@ public ResponseEntity<StreamingResponseBody> asyncDownloadSingleResource(@NotBla
}));
}

@Override
public SerializableStatObjectResponse stateObject(@NotBlank String bucket, @NotBlank String object) {
return SerializableStatObjectResponse.build(this.minioHelper.statObject(bucket, object));
}

@SuppressWarnings("DuplicatedCode")
private ResponseEntity<StreamingResponseBody> asyncGetResourceRegion(String bucket, String object,
StatObjectResponse statObjectResponse,
List<HttpRange> httpRanges) {
val getObjectResponse = this.minioHelper.getObject(bucket, object, httpRanges.get(0).getRangeStart(0),
MEDIUM_CHUNK_SIZE.toBytes());
LARGE_CHUNK_SIZE.toBytes());
val start = httpRanges.get(0).getRangeStart(0);
var end = start + MEDIUM_CHUNK_SIZE.toBytes() - 1;
var end = start + LARGE_CHUNK_SIZE.toBytes() - 1;
val resourceLength = statObjectResponse.size();
end = Math.min(end, resourceLength - 1);
val rangeLength = end - start + 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
package com.jmsoftware.maf.osscenter.write.controller;

import com.jmsoftware.maf.common.bean.ResponseBodyBean;
import com.jmsoftware.maf.common.exception.BizException;
import com.jmsoftware.maf.osscenter.write.entity.MergeResourceChunkPayload;
import com.jmsoftware.maf.osscenter.write.entity.ObjectResponse;
import com.jmsoftware.maf.osscenter.write.entity.UploadResourceChunkPayload;
import com.jmsoftware.maf.osscenter.write.service.WriteResourceService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import javax.validation.Valid;

/**
* <h1>WriteResourceController</h1>
Expand All @@ -33,11 +32,23 @@ public class WriteResourceController {
private final MessageSource messageSource;

@PostMapping("/upload/single")
@SneakyThrows({IOException.class, BizException.class})
@ApiOperation(value = "Upload single resource", notes = "Upload single resource")
public ResponseBodyBean<String> uploadSingleResource(@RequestParam("file") MultipartFile multipartFile) {
public ResponseBodyBean<ObjectResponse> uploadSingleResource(@RequestParam("file") MultipartFile multipartFile) {
return ResponseBodyBean.ofSuccess(this.writeResourceService.uploadSingleResource(multipartFile),
this.messageSource.getMessage("uploaded", null,
LocaleContextHolder.getLocale()));
}

@PostMapping("/upload/chunk")
@ApiOperation(value = "Upload chunk of resource", notes = "Upload chunk of resource")
public ResponseBodyBean<ObjectResponse> uploadResourceChunk(@RequestParam("file") MultipartFile multipartFile,
@Valid UploadResourceChunkPayload payload) {
return ResponseBodyBean.ofSuccess(this.writeResourceService.uploadResourceChunk(multipartFile, payload));
}

@PutMapping("/merge/chunk")
@ApiOperation(value = "Merge chunk of resource", notes = "Merge chunk of resource")
public ResponseBodyBean<ObjectResponse> mergeResourceChunk(@Valid @RequestBody MergeResourceChunkPayload payload) {
return ResponseBodyBean.ofSuccess(this.writeResourceService.mergeResourceChunk(payload));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.jmsoftware.maf.osscenter.write.entity;

import lombok.Data;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import java.util.List;

/**
* Description: MergeResourceChunkPayload, change description here.
*
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com, date: 8/12/2021 8:48 PM
**/
@Data
public class MergeResourceChunkPayload {
@NotBlank
private String bucket;
@NotEmpty
private List<@Valid @NotBlank String> objectList;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.jmsoftware.maf.osscenter.write.entity;

import lombok.Data;

/**
* Description: ObjectResponse, change description here.
*
* @author Johnny Miller (锺俊), email: johnnysviva@outlook.com, date: 8/12/2021 9:27 PM
**/
@Data
public class ObjectResponse {
private String bucket;
private String object;
private String etag;
}
Loading

0 comments on commit a976f19

Please sign in to comment.