some fixes
This commit is contained in:
parent
6f8f28fc28
commit
2207390eb2
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,3 +5,7 @@ target
|
||||
.classpath
|
||||
.project
|
||||
.claude
|
||||
.vscode
|
||||
.DS_Store
|
||||
*.log
|
||||
plans
|
||||
2
pom.xml
2
pom.xml
@ -43,7 +43,7 @@
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<transformers>
|
||||
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||
<mainClass>cz.kamma.fabka.httpserver.HttpServerApplication</mainClass>
|
||||
<mainClass>cz.kamma.fabka.app.HttpServerApplication</mainClass>
|
||||
</transformer>
|
||||
</transformers>
|
||||
</configuration>
|
||||
|
||||
@ -9,6 +9,7 @@ import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import cz.kamma.fabka.repository.model.ChatLine;
|
||||
import cz.kamma.fabka.repository.model.ChatVoteStats;
|
||||
@ -83,23 +84,26 @@ public class ChatRepository {
|
||||
if (chatId <= 0) {
|
||||
return new ChatVoteStats("", "");
|
||||
}
|
||||
long startTime = System.nanoTime();
|
||||
ChatVoteStats result = null;
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(CHAT_VOTES_USERS_SQL)) {
|
||||
ps.setLong(1, chatId);
|
||||
ps.setLong(2, chatId);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (!rs.next()) {
|
||||
return new ChatVoteStats("", "");
|
||||
if (rs.next()) {
|
||||
result = new ChatVoteStats(
|
||||
valueOrDefault(rs.getString("thumbup"), ""),
|
||||
valueOrDefault(rs.getString("thumbdown"), "")
|
||||
);
|
||||
}
|
||||
return new ChatVoteStats(
|
||||
valueOrDefault(rs.getString("thumbup"), ""),
|
||||
valueOrDefault(rs.getString("thumbdown"), "")
|
||||
);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return new ChatVoteStats("", "");
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
System.out.println("[DEBUG] CHAT_VOTES_USERS_SQL: chatId=" + chatId + ", duration=" + durationMs + "ms");
|
||||
return result != null ? result : new ChatVoteStats("", "");
|
||||
}
|
||||
|
||||
public void addChatMessage(long userId, String message) {
|
||||
@ -123,6 +127,7 @@ public class ChatRepository {
|
||||
return lines;
|
||||
}
|
||||
int safeLimit = limit <= 0 ? 40 : limit;
|
||||
long startTime = System.nanoTime();
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(CHAT_LINES_SQL)) {
|
||||
ps.setLong(1, currentUserId);
|
||||
@ -146,6 +151,8 @@ public class ChatRepository {
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
System.out.println("[DEBUG] CHAT_LINES_SQL: userId=" + currentUserId + ", limit=" + safeLimit + ", lines=" + lines.size() + ", duration=" + durationMs + "ms");
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
@ -16,6 +16,7 @@ import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import cz.kamma.fabka.repository.model.AttachmentData;
|
||||
import cz.kamma.fabka.repository.model.ForumAttachment;
|
||||
@ -30,6 +31,16 @@ public class ForumRepository {
|
||||
private static final ZoneId APP_ZONE = ZoneId.of("Europe/Prague");
|
||||
private static final String FORUM_DETAIL_SQL =
|
||||
"SELECT id, name, description, countdown FROM forum WHERE id=? AND active=1 LIMIT 1";
|
||||
private static final String FORUM_MESSAGES_SQL_DEBUG =
|
||||
"SELECT fi.id, fi.text, fi.created, fi.quoteitem, fi.sticky, ua.id AS author_id, ua.username, ua.created AS author_created, ua.city, " +
|
||||
" (SELECT COUNT(*) FROM forum_items fi2 WHERE fi2.createdby=ua.id AND fi2.deleted=0) AS author_posts, " +
|
||||
" COALESCE((SELECT SUM(votevalue) FROM voting v WHERE v.forumitemid=fi.id), 0) AS vvalue, " +
|
||||
" (SELECT COUNT(*) FROM voting v WHERE v.forumitemid=fi.id AND v.votevalue=1) AS vote_yes, " +
|
||||
" (SELECT COUNT(*) FROM voting v WHERE v.forumitemid=fi.id AND v.votevalue=-1) AS vote_no, " +
|
||||
" (SELECT GROUP_CONCAT(ua2.username SEPARATOR ',') FROM voting v JOIN user_accounts ua2 ON ua2.id=v.voteby WHERE v.forumitemid=fi.id AND v.votevalue=1) AS vote_yes_users, " +
|
||||
" (SELECT GROUP_CONCAT(ua2.username SEPARATOR ',') FROM voting v JOIN user_accounts ua2 ON ua2.id=v.voteby WHERE v.forumitemid=fi.id AND v.votevalue=-1) AS vote_no_users " +
|
||||
"FROM forum_items fi JOIN user_accounts ua ON ua.id=fi.createdby " +
|
||||
"WHERE fi.forumid=? AND fi.deleted=0 ORDER BY fi.created DESC";
|
||||
private static final String QUOTED_ITEM_SQL =
|
||||
"SELECT fi.text, ua.username FROM forum_items fi JOIN user_accounts ua ON ua.id=fi.createdby WHERE fi.id=? LIMIT 1";
|
||||
private static final String ATTACHMENTS_SQL =
|
||||
@ -104,6 +115,7 @@ public class ForumRepository {
|
||||
|
||||
public List<ForumSummary> listActiveForums() {
|
||||
List<ForumSummary> forums = new ArrayList<>();
|
||||
long startTime = System.nanoTime();
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(FORUM_SQL);
|
||||
ResultSet rs = ps.executeQuery()) {
|
||||
@ -122,6 +134,8 @@ public class ForumRepository {
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
System.out.println("[DEBUG] FORUM_SQL: forums=" + forums.size() + ", duration=" + durationMs + "ms");
|
||||
return forums;
|
||||
}
|
||||
|
||||
@ -144,6 +158,7 @@ public class ForumRepository {
|
||||
if (userId <= 0) {
|
||||
return result;
|
||||
}
|
||||
long startTime = System.nanoTime();
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(NEW_MESSAGES_COUNT_SQL)) {
|
||||
ps.setLong(1, userId);
|
||||
@ -159,6 +174,8 @@ public class ForumRepository {
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
System.out.println("[DEBUG] NEW_MESSAGES_COUNT_SQL: userId=" + userId + ", forums=" + result.size() + ", duration=" + durationMs + "ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -166,24 +183,27 @@ public class ForumRepository {
|
||||
if (forumId <= 0) {
|
||||
return null;
|
||||
}
|
||||
long startTime = System.nanoTime();
|
||||
ForumDetail result = null;
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(FORUM_DETAIL_SQL)) {
|
||||
ps.setLong(1, forumId);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (!rs.next()) {
|
||||
return null;
|
||||
if (rs.next()) {
|
||||
result = new ForumDetail(
|
||||
rs.getLong("id"),
|
||||
rs.getString("name"),
|
||||
rs.getString("description"),
|
||||
rs.getString("countdown")
|
||||
);
|
||||
}
|
||||
return new ForumDetail(
|
||||
rs.getLong("id"),
|
||||
rs.getString("name"),
|
||||
rs.getString("description"),
|
||||
rs.getString("countdown")
|
||||
);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
System.out.println("[DEBUG] FORUM_DETAIL_SQL: forumId=" + forumId + ", duration=" + durationMs + "ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<ForumMessage> listMessagesByForumId(long forumId) {
|
||||
@ -191,46 +211,103 @@ public class ForumRepository {
|
||||
if (forumId <= 0) {
|
||||
return messages;
|
||||
}
|
||||
if (!loadMessages(messages, forumId, FORUM_MESSAGES_SQL)) {
|
||||
long startTime = System.nanoTime();
|
||||
if (!loadMessages(messages, forumId, FORUM_MESSAGES_SQL_DEBUG)) {
|
||||
loadMessages(messages, forumId, FORUM_MESSAGES_SQL_NO_STICKY);
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
System.out.println("[DEBUG] FORUM_MESSAGES_SQL: forumId=" + forumId + ", rows=" + messages.size() + ", duration=" + durationMs + "ms");
|
||||
return messages;
|
||||
}
|
||||
|
||||
private boolean loadMessages(List<ForumMessage> out, long forumId, String sql) {
|
||||
out.clear();
|
||||
long queryStartTime = System.nanoTime();
|
||||
|
||||
// First, fetch all messages and collect item IDs for batch attachment loading
|
||||
List<Long> itemIds = new ArrayList<>();
|
||||
List<Timestamp> createdTimes = new ArrayList<>();
|
||||
List<Long> authorIds = new ArrayList<>();
|
||||
List<String> usernames = new ArrayList<>();
|
||||
List<String> cities = new ArrayList<>();
|
||||
List<String> texts = new ArrayList<>();
|
||||
List<Long> authorPostCounts = new ArrayList<>();
|
||||
List<Integer> vvalues = new ArrayList<>();
|
||||
List<Integer> voteYes = new ArrayList<>();
|
||||
List<Integer> voteNo = new ArrayList<>();
|
||||
List<String> voteYesUsers = new ArrayList<>();
|
||||
List<String> voteNoUsers = new ArrayList<>();
|
||||
List<Long> ids = new ArrayList<>();
|
||||
List<Long> quoteItemIds = new ArrayList<>();
|
||||
List<Integer> stickies = new ArrayList<>();
|
||||
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setLong(1, forumId);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
Timestamp createdTs = rs.getTimestamp("created");
|
||||
long quoteItemId = rs.getLong("quoteitem");
|
||||
QuotedTextItem quotedItem = quoteItemId > 0 ? findQuotedItem(quoteItemId) : null;
|
||||
out.add(new ForumMessage(
|
||||
rs.getLong("id"),
|
||||
rs.getLong("author_id"),
|
||||
valueOrDefault(rs.getString("username"), "N/A"),
|
||||
formatTs(rs.getTimestamp("author_created")),
|
||||
valueOrDefault(rs.getString("city"), ""),
|
||||
rs.getLong("author_posts"),
|
||||
createdTs == null ? 0L : createdTs.getTime(),
|
||||
rs.getInt("vvalue"),
|
||||
rs.getInt("vote_yes"),
|
||||
rs.getInt("vote_no"),
|
||||
valueOrDefault(rs.getString("vote_yes_users"), ""),
|
||||
valueOrDefault(rs.getString("vote_no_users"), ""),
|
||||
quoteItemId,
|
||||
quotedItem,
|
||||
formatTs(createdTs),
|
||||
valueOrDefault(rs.getString("text"), ""),
|
||||
listAttachmentsByForumItemId(rs.getLong("id")),
|
||||
rs.getInt("sticky") == 1
|
||||
));
|
||||
ids.add(rs.getLong("id"));
|
||||
itemIds.add(rs.getLong("id"));
|
||||
createdTimes.add(rs.getTimestamp("created"));
|
||||
authorIds.add(rs.getLong("author_id"));
|
||||
usernames.add(rs.getString("username"));
|
||||
cities.add(rs.getString("city"));
|
||||
authorPostCounts.add(rs.getLong("author_posts"));
|
||||
texts.add(rs.getString("text"));
|
||||
vvalues.add(rs.getInt("vvalue"));
|
||||
voteYes.add(rs.getInt("vote_yes"));
|
||||
voteNo.add(rs.getInt("vote_no"));
|
||||
voteYesUsers.add(rs.getString("vote_yes_users"));
|
||||
voteNoUsers.add(rs.getString("vote_no_users"));
|
||||
quoteItemIds.add(rs.getLong("quoteitem"));
|
||||
stickies.add(rs.getInt("sticky"));
|
||||
}
|
||||
}
|
||||
|
||||
// Batch load attachments for all items
|
||||
long attachmentsStartTime = System.nanoTime();
|
||||
Map<Long, List<ForumAttachment>> attachmentsByItemId = new LinkedHashMap<>();
|
||||
if (!itemIds.isEmpty()) {
|
||||
attachmentsByItemId = loadAttachmentsBatch(itemIds);
|
||||
}
|
||||
long attachmentsDurationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - attachmentsStartTime);
|
||||
System.out.println("[DEBUG] Batch attachment load: " + attachmentsDurationMs + "ms, " + itemIds.size() + " items");
|
||||
|
||||
// Build message objects
|
||||
for (int i = 0; i < ids.size(); i++) {
|
||||
long messageId = ids.get(i);
|
||||
long quoteItemId = quoteItemIds.get(i);
|
||||
QuotedTextItem quotedItem = quoteItemId > 0 ? findQuotedItem(quoteItemId) : null;
|
||||
List<ForumAttachment> attachments = attachmentsByItemId.getOrDefault(messageId, new ArrayList<>());
|
||||
|
||||
out.add(new ForumMessage(
|
||||
messageId,
|
||||
authorIds.get(i),
|
||||
valueOrDefault(usernames.get(i), "N/A"),
|
||||
formatTs(createdTimes.get(i)),
|
||||
valueOrDefault(cities.get(i), ""),
|
||||
authorPostCounts.get(i),
|
||||
createdTimes.get(i) == null ? 0L : createdTimes.get(i).getTime(),
|
||||
vvalues.get(i),
|
||||
voteYes.get(i),
|
||||
voteNo.get(i),
|
||||
valueOrDefault(voteYesUsers.get(i), ""),
|
||||
valueOrDefault(voteNoUsers.get(i), ""),
|
||||
quoteItemId,
|
||||
quotedItem,
|
||||
formatTs(createdTimes.get(i)),
|
||||
valueOrDefault(texts.get(i), ""),
|
||||
attachments,
|
||||
stickies.get(i) == 1
|
||||
));
|
||||
}
|
||||
|
||||
long totalDurationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - queryStartTime);
|
||||
System.out.println("[DEBUG] loadMessages completed: total=" + totalDurationMs + "ms, rows=" + out.size());
|
||||
return true;
|
||||
} catch (Exception ex) {
|
||||
System.err.println("[DEBUG] loadMessages ERROR: " + ex.getMessage());
|
||||
ex.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -374,22 +451,25 @@ public class ForumRepository {
|
||||
if (messageId <= 0) {
|
||||
return null;
|
||||
}
|
||||
long startTime = System.nanoTime();
|
||||
QuotedTextItem result = null;
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(QUOTED_ITEM_SQL)) {
|
||||
ps.setLong(1, messageId);
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
if (!rs.next()) {
|
||||
return null;
|
||||
if (rs.next()) {
|
||||
result = new QuotedTextItem(
|
||||
valueOrDefault(rs.getString("username"), "N/A"),
|
||||
valueOrDefault(rs.getString("text"), "")
|
||||
);
|
||||
}
|
||||
return new QuotedTextItem(
|
||||
valueOrDefault(rs.getString("username"), "N/A"),
|
||||
valueOrDefault(rs.getString("text"), "")
|
||||
);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
System.out.println("[DEBUG] QUOTED_ITEM_SQL: messageId=" + messageId + ", duration=" + durationMs + "ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
public long addReply(long forumId, long userId, String message, Long quoteItem) {
|
||||
@ -509,6 +589,7 @@ public class ForumRepository {
|
||||
if (forumItemId <= 0) {
|
||||
return out;
|
||||
}
|
||||
long startTime = System.nanoTime();
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(ATTACHMENTS_SQL)) {
|
||||
ps.setLong(1, forumItemId);
|
||||
@ -525,6 +606,10 @@ public class ForumRepository {
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
if (durationMs > 1) {
|
||||
System.out.println("[DEBUG] ATTACHMENTS_SQL: forumItemId=" + forumItemId + ", count=" + out.size() + ", duration=" + durationMs + "ms");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -559,6 +644,36 @@ public class ForumRepository {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<Long, List<ForumAttachment>> loadAttachmentsBatch(List<Long> itemIds) {
|
||||
Map<Long, List<ForumAttachment>> result = new LinkedHashMap<>();
|
||||
if (itemIds.isEmpty()) {
|
||||
return result;
|
||||
}
|
||||
String sql = "SELECT forumitemsid, id, name, ispicture, width, size FROM attachments WHERE forumitemsid IN (" +
|
||||
String.join(",", java.util.Collections.nCopies(itemIds.size(), "?")) + ") ORDER BY forumitemsid, id";
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
for (int i = 0; i < itemIds.size(); i++) {
|
||||
ps.setLong(i + 1, itemIds.get(i));
|
||||
}
|
||||
try (ResultSet rs = ps.executeQuery()) {
|
||||
while (rs.next()) {
|
||||
long forumItemId = rs.getLong("forumitemsid");
|
||||
ForumAttachment attachment = new ForumAttachment(
|
||||
rs.getLong("id"),
|
||||
valueOrDefault(rs.getString("name"), "attachment"),
|
||||
rs.getInt("ispicture") == 1,
|
||||
rs.getInt("width")
|
||||
);
|
||||
result.computeIfAbsent(forumItemId, k -> new ArrayList<>()).add(attachment);
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static String valueOrDefault(String value, String defaultValue) {
|
||||
return value == null || value.isBlank() ? defaultValue : value;
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import cz.kamma.fabka.repository.model.PrivateMessageItem;
|
||||
import cz.kamma.fabka.repository.model.PrivateMessageStats;
|
||||
@ -56,6 +57,7 @@ public class PrivateMessageRepository {
|
||||
"where (m.to_user=? or m.from_user=?) and m.deleted=0 and m.reply_to is null " +
|
||||
"order by " + order;
|
||||
|
||||
long startTime = System.nanoTime();
|
||||
try (Connection conn = DriverManager.getConnection(jdbcUrl, jdbcUser, jdbcPassword);
|
||||
PreparedStatement ps = conn.prepareStatement(sql)) {
|
||||
ps.setLong(1, userId);
|
||||
@ -77,6 +79,8 @@ public class PrivateMessageRepository {
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
long durationMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
|
||||
System.out.println("[DEBUG] PM listThreads: userId=" + userId + ", threads=" + out.size() + ", duration=" + durationMs + "ms");
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user