refactor(media)!: unify processing under asynchronous job workflow #3
@@ -1,6 +1,6 @@
|
||||
package com.ddf.vodsystem.controllers.dto;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Instant;
|
||||
|
||||
public record ClipResponse(
|
||||
Long id,
|
||||
@@ -8,5 +8,5 @@ public record ClipResponse(
|
||||
String title,
|
||||
String description,
|
||||
Float duration,
|
||||
LocalDateTime createdAt
|
||||
Instant createdAt
|
||||
) {}
|
||||
@@ -5,7 +5,7 @@ import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name = "clips")
|
||||
@@ -28,7 +28,7 @@ public class Clip {
|
||||
private String description;
|
||||
|
||||
@Column(name = "created_at")
|
||||
private LocalDateTime createdAt;
|
||||
private Instant createdAt;
|
||||
|
||||
@Column(name = "width", nullable = false)
|
||||
private Integer width;
|
||||
|
||||
@@ -4,7 +4,7 @@ import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name = "streams")
|
||||
@@ -21,11 +21,11 @@ public class Stream {
|
||||
private User user;
|
||||
|
||||
@Column(name = "start_time")
|
||||
private LocalDateTime startDate;
|
||||
private Instant startDate;
|
||||
|
||||
@Column(name = "end_time")
|
||||
private LocalDateTime endDate;
|
||||
private Instant endDate;
|
||||
|
||||
@Column(name = "last_seen")
|
||||
private LocalDateTime lastSeen;
|
||||
private Instant lastSeen;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package com.ddf.vodsystem.entities;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users")
|
||||
@@ -33,7 +33,7 @@ public class User {
|
||||
private Integer role; // 0: user, 1: admin
|
||||
|
||||
@Column(name = "created_at")
|
||||
private LocalDateTime createdAt;
|
||||
private Instant createdAt;
|
||||
|
||||
@Column(name = "stream_key")
|
||||
private String streamKey;
|
||||
|
||||
@@ -5,7 +5,7 @@ import com.ddf.vodsystem.entities.User;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -13,5 +13,5 @@ import java.util.Optional;
|
||||
public interface StreamRepository extends JpaRepository<Stream, Long> {
|
||||
Optional<Stream> findByUserAndEndDateIsNull(User user);
|
||||
List<Stream> findByUser(User user);
|
||||
List<Stream> findByEndDateIsNullAndLastSeenBefore(LocalDateTime cutoff);
|
||||
List<Stream> findByEndDateIsNullAndLastSeenBefore(Instant cutoff);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -208,7 +208,7 @@ public class ClipService {
|
||||
clip.setUser(user);
|
||||
clip.setTitle(options.getTitle() != null ? options.getTitle() : "Untitled Clip");
|
||||
clip.setDescription(options.getDescription() != null ? options.getDescription() : "");
|
||||
clip.setCreatedAt(LocalDateTime.now());
|
||||
clip.setCreatedAt(Instant.now());
|
||||
clip.setWidth(options.getWidth());
|
||||
clip.setHeight(options.getHeight());
|
||||
clip.setFps(options.getFps());
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
|
||||
@Service
|
||||
@@ -37,7 +37,7 @@ public class StreamService {
|
||||
throw new AlreadyStreaming("User " + user.getUsername() + " is already streaming.");
|
||||
});
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
Instant now = Instant.now();
|
||||
Stream stream = new Stream();
|
||||
stream.setUser(user);
|
||||
stream.setStartDate(now);
|
||||
@@ -52,7 +52,7 @@ public class StreamService {
|
||||
.orElseThrow(() -> new IllegalStateException(
|
||||
"No active stream found for user " + user.getUsername()));
|
||||
|
||||
stream.setEndDate(LocalDateTime.now());
|
||||
stream.setEndDate(Instant.now());
|
||||
streamRepository.saveAndFlush(stream);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ public class StreamService {
|
||||
.orElseThrow(() -> new IllegalStateException(
|
||||
"No active stream found for user " + user.getUsername()));
|
||||
|
||||
stream.setLastSeen(LocalDateTime.now());
|
||||
stream.setLastSeen(Instant.now());
|
||||
streamRepository.saveAndFlush(stream);
|
||||
}
|
||||
|
||||
@@ -97,11 +97,11 @@ public class StreamService {
|
||||
@Scheduled(fixedDelay = 30_000)
|
||||
@Transactional
|
||||
public void endStaleStreams() {
|
||||
LocalDateTime cutoff = LocalDateTime.now().minusSeconds(HEARTBEAT_TIMEOUT_SECONDS);
|
||||
Instant cutoff = Instant.now().minusSeconds(HEARTBEAT_TIMEOUT_SECONDS);
|
||||
List<Stream> stale = streamRepository.findByEndDateIsNullAndLastSeenBefore(cutoff);
|
||||
if (stale.isEmpty()) return;
|
||||
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
Instant now = Instant.now();
|
||||
for (Stream stream : stale) {
|
||||
stream.setEndDate(now);
|
||||
logger.warn("Stream {} for user {} ended due to heartbeat timeout", stream.getId(), stream.getUser().getUsername());
|
||||
|
||||
@@ -17,7 +17,7 @@ import org.springframework.stereotype.Service;
|
||||
import java.io.IOException;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.SecureRandom;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.Instant;
|
||||
import java.util.Collections;
|
||||
import java.util.HexFormat;
|
||||
import java.util.Optional;
|
||||
@@ -77,7 +77,7 @@ public class UserService {
|
||||
|
||||
if (existingUser.isEmpty()) {
|
||||
user.setRole(0);
|
||||
user.setCreatedAt(LocalDateTime.now());
|
||||
user.setCreatedAt(Instant.now());
|
||||
user.setStreamKey(generateStreamKey());
|
||||
return userRepository.saveAndFlush(user);
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class CompressionService {
|
||||
outputFile,
|
||||
clipOptions
|
||||
);
|
||||
CommandOutput result = CommandRunner.run(command, line -> setProgress(line, progress, clipOptions.getDuration()));
|
||||
CommandOutput result = CommandRunner.run(command, line -> CommandRunner.setProgress(line, progress, clipOptions.getDuration()));
|
||||
progress.markComplete();
|
||||
|
||||
return CompletableFuture.completedFuture(result);
|
||||
|
||||
@@ -72,6 +72,7 @@ public class StreamActionsService {
|
||||
logger.info("Saving section with ({} segments) to '{}'",
|
||||
segments.size(), outputFile);
|
||||
CommandRunner.run(command, line -> CommandRunner.setProgress(line, progressTracker, duration));
|
||||
progressTracker.markComplete();
|
||||
|
||||
return CompletableFuture.completedFuture(outputFile);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
spring.docker.compose.file=docker-compose.dev.yml
|
||||
|
||||
media.temp.inputs=./video/inputs
|
||||
media.temp.inputs=./videos/inputs
|
||||
media.temp.outputs=./videos/outputs
|
||||
media.users=${MEDIA_DATA}
|
||||
media.streams=${STREAM_DATA}
|
||||
@@ -31,4 +31,7 @@ media.users=/app/media/
|
||||
media.streams=/app/stream/
|
||||
|
||||
## Server Configuration
|
||||
server.servlet.session.timeout=30m
|
||||
server.servlet.session.timeout=30m
|
||||
|
||||
# Serialize Instant as ISO-8601 UTC string (not epoch seconds)
|
||||
spring.jackson.serialization.write-dates-as-timestamps=false
|
||||
@@ -10,7 +10,7 @@ CREATE TABLE IF NOT EXISTS users (
|
||||
name VARCHAR(100) NOT NULL,
|
||||
profile_picture_url VARCHAR(255),
|
||||
role INTEGER DEFAULT 0,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
stream_key VARCHAR(64) NOT NULL UNIQUE
|
||||
);
|
||||
|
||||
@@ -29,7 +29,7 @@ CREATE TABLE IF NOT EXISTS clips (
|
||||
user_id BIGINT NOT NULL,
|
||||
title VARCHAR(255) NOT NULL,
|
||||
description TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
width INTEGER NOT NULL,
|
||||
height INTEGER NOT NULL,
|
||||
fps FLOAT NOT NULL,
|
||||
|
||||
Reference in New Issue
Block a user