Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Тузиков Александр, ИТМО DWS, Stage 1 #6

Merged
merged 18 commits into from
Feb 29, 2024
Merged
28 changes: 28 additions & 0 deletions src/main/java/ru/vk/itmo/test/tuzikovalexandr/Server.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package ru.vk.itmo.test.tuzikovalexandr;

import ru.vk.itmo.ServiceConfig;
import ru.vk.itmo.dao.Config;
import ru.vk.itmo.dao.Dao;
import ru.vk.itmo.test.reference.dao.ReferenceDao;

import java.io.IOException;
import java.nio.file.Files;
import java.util.List;

public final class Server {

private Server() {

}

public static void main(String[] args) throws IOException {
long flushThresholdBytes = 1024 * 1024;
Dao dao = new ReferenceDao(new Config(Files.createTempDirectory("data"), flushThresholdBytes));
ServerImpl server = new ServerImpl(new ServiceConfig(
8080, "http://localhost",
List.of("http://localhost"),
Files.createTempDirectory("data")
), dao);
server.start();
}
}
127 changes: 127 additions & 0 deletions src/main/java/ru/vk/itmo/test/tuzikovalexandr/ServerImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package ru.vk.itmo.test.tuzikovalexandr;

import one.nio.http.HttpException;
import one.nio.http.HttpServer;
import one.nio.http.HttpServerConfig;
import one.nio.http.HttpSession;
import one.nio.http.Param;
import one.nio.http.Path;
import one.nio.http.Request;
import one.nio.http.RequestMethod;
import one.nio.http.Response;
import one.nio.server.AcceptorConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.vk.itmo.ServiceConfig;
import ru.vk.itmo.dao.BaseEntry;
import ru.vk.itmo.dao.Dao;
import ru.vk.itmo.dao.Entry;

import java.io.IOException;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.nio.charset.StandardCharsets;
import java.util.Set;

public class ServerImpl extends HttpServer {

private final Dao dao;
private static final Logger log = LoggerFactory.getLogger(ServerImpl.class);
private static final Set<Integer> METHODS = Set.of(
Request.METHOD_GET, Request.METHOD_PUT, Request.METHOD_DELETE
);

public ServerImpl(ServiceConfig config, Dao dao) throws IOException {
super(createServerConfig(config));
this.dao = dao;
}

private static HttpServerConfig createServerConfig(ServiceConfig serviceConfig) {
HttpServerConfig serverConfig = new HttpServerConfig();
AcceptorConfig acceptorConfig = new AcceptorConfig();
acceptorConfig.port = serviceConfig.selfPort();
acceptorConfig.reusePort = true;

serverConfig.acceptors = new AcceptorConfig[] {acceptorConfig};
serverConfig.closeSessions = true;
return serverConfig;
}

@Override
public void handleDefault(Request request, HttpSession session) throws IOException {
Response response;
if (METHODS.contains(request.getMethod())) {
response = new Response(Response.BAD_REQUEST, Response.EMPTY);
} else {
response = new Response(Response.METHOD_NOT_ALLOWED, Response.EMPTY);
}
session.sendResponse(response);
}

@Override
public void handleRequest(Request request, HttpSession session) throws IOException {
try {
super.handleRequest(request, session);
} catch (Exception e) {
if (e.getClass() == HttpException.class) {
session.sendResponse(new Response(Response.BAD_REQUEST, Response.EMPTY));
} else {
log.error("Exception during handleRequest: ", e);
session.sendResponse(new Response(Response.INTERNAL_ERROR, Response.EMPTY));
}
}
}

@Path(value = "/v0/status")
public Response status() {
return Response.ok("OK");
}

@Path(value = "/v0/entity")
@RequestMethod(Request.METHOD_GET)
public Response getEntry(@Param(value = "id", required = true) String id) {
if (id.isEmpty() || id.isBlank()) {
return new Response(Response.BAD_REQUEST, Response.EMPTY);
}

MemorySegment key = fromString(id);
Entry<MemorySegment> entry = dao.get(key);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Здесь и ниже никак не обрабатываются возможные исключения DAO.


if (entry == null) {
return new Response(Response.NOT_FOUND, Response.EMPTY);
}

return new Response(Response.OK, entry.value().toArray(ValueLayout.JAVA_BYTE));
}

@Path(value = "/v0/entity")
@RequestMethod(Request.METHOD_PUT)
public Response putEntry(@Param(value = "id", required = true) String id, Request request) {
if (id.isEmpty() || id.isBlank() || request.getBody() == null) {
return new Response(Response.BAD_REQUEST, Response.EMPTY);
}

MemorySegment key = fromString(id);
MemorySegment value = MemorySegment.ofArray(request.getBody());

dao.upsert(new BaseEntry<>(key, value));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Если тела запроса нет, то PUT превратится в DELETE? Выглядит не очень корректно.

return new Response(Response.CREATED, Response.EMPTY);
}

@Path(value = "/v0/entity")
@RequestMethod(Request.METHOD_DELETE)
public Response deleteEntry(@Param(value = "id", required = true) String id) {
if (id.isEmpty() || id.isBlank()) {
return new Response(Response.BAD_REQUEST, Response.EMPTY);
}

MemorySegment key = fromString(id);
dao.upsert(new BaseEntry<>(key, null));

return new Response(Response.ACCEPTED, Response.EMPTY);
}

private MemorySegment fromString(String data) {
return data == null ? null : MemorySegment.ofArray(data.getBytes(StandardCharsets.UTF_8));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Разве null допустим?

Suggested change
return data == null ? null : MemorySegment.ofArray(data.getBytes(StandardCharsets.UTF_8));
return MemorySegment.ofArray(data.getBytes(StandardCharsets.UTF_8));

}
}
46 changes: 46 additions & 0 deletions src/main/java/ru/vk/itmo/test/tuzikovalexandr/ServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package ru.vk.itmo.test.tuzikovalexandr;

import ru.vk.itmo.Service;
import ru.vk.itmo.ServiceConfig;
import ru.vk.itmo.dao.Config;
import ru.vk.itmo.dao.Dao;
import ru.vk.itmo.test.ServiceFactory;
import ru.vk.itmo.test.reference.dao.ReferenceDao;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;

public class ServiceImpl implements Service {

private final ServiceConfig config;
private ServerImpl server;
private Dao dao;

public ServiceImpl(ServiceConfig config) {
this.config = config;
}

@Override
public CompletableFuture<Void> start() throws IOException {
dao = new ReferenceDao(new Config(config.workingDir(), 1024 * 1024));
server = new ServerImpl(config, dao);
server.start();
return CompletableFuture.completedFuture(null);
}

@Override
public CompletableFuture<Void> stop() throws IOException {
server.stop();
dao.close();
return CompletableFuture.completedFuture(null);
}

@ServiceFactory(stage = 1)
public static class Factory implements ServiceFactory.Factory {

@Override
public Service create(ServiceConfig config) {
return new ServiceImpl(config);
}
}
}
Loading
Loading