Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions build.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,12 @@ def _normalize_arch(machine: str) -> Optional[str]:


def _normalize_os() -> Optional[str]:
"""
Normalize platform system name to a standard string.
Maps 'android' and 'linux' systems to 'linux'.
"""
system = platform.system().lower()
if system == "linux":
if system in {"linux", "android"}:
return "linux"
if system == "darwin":
return "macos"
Expand Down Expand Up @@ -262,6 +266,10 @@ def build_module(
release: bool = False,
verbose: bool = False,
) -> tuple[bool, float, str]:
"""
Build a single project module by running its compile/build commands.
Supports special handling for Node.js/frontend install step under Android.
"""

print(f"\n {color('▸', Colors.CYAN)} Building {color(module.name, Colors.BOLD)} ({module.language})...")

Expand All @@ -288,6 +296,8 @@ def build_module(
return False, time.time() - start, f"npm install failed:\n{install_result.stderr}"
except subprocess.TimeoutExpired:
return False, time.time() - start, "npm install TIMEOUT (120s)"
except FileNotFoundError as e:
return False, time.time() - start, f"Command not found: {e}"

if module.name == "engine":

Expand Down Expand Up @@ -590,7 +600,14 @@ def generate_logd(
)
return False

safe_pw = sr.stdout.strip()
import re
stdout_clean = sr.stdout.strip()
tokens = re.findall(r'\b[0-9a-fA-F]{20,64}\b', stdout_clean)
if tokens:
safe_pw = tokens[-1]
else:
safe_pw = stdout_clean.split()[-1] if stdout_clean else ""

logd_files = split_diagnostic_logd(logd_path)
logd_relpaths = [str(path.relative_to(ROOT)) for path in logd_files]
decrypt_target = logd_relpaths[0] if len(logd_relpaths) == 1 else str(logd_path.relative_to(ROOT))
Expand Down
23 changes: 0 additions & 23 deletions diagnostic/build-00000000.json

This file was deleted.

1 change: 0 additions & 1 deletion diagnostic/build-00000000.logd

This file was deleted.

86 changes: 86 additions & 0 deletions diagnostic/build-36b7be47.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"generated_at": "2026-06-21T02:21:28.599525+00:00",
"commit": "36b7be47",
"diagnostic_logd": "diagnostic/build-36b7be47.logd",
"diagnostic_logd_error": null,
"chunked": false,
"chunk_size_bytes": null,
"password": "68086257577bc9c0f93d",
"decrypt_command": "encryptly unpack diagnostic/build-36b7be47.logd <outdir> --password 68086257577bc9c0f93d",
"total_modules": 10,
"passed": 2,
"failed": 8,
"modules": [
{
"name": "backend",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'cargo'"
},
{
"name": "frontend",
"status": "FAIL",
"elapsed_seconds": 0.922,
"artifact": null,
"output": "> tent-frontend@0.0.0 build\n> tsc -b && vite build\nsh: 1: tsc: not found"
},
{
"name": "market",
"status": "PASS",
"elapsed_seconds": 3.433,
"artifact": "/data/data/com.termux/files/home/jackjin-tentoftrials/market/market",
"output": ""
},
{
"name": "frailbox",
"status": "PASS",
"elapsed_seconds": 0.04,
"artifact": "/data/data/com.termux/files/home/jackjin-tentoftrials/frailbox/frailbox",
"output": "make: Nothing to be done for 'all'."
},
{
"name": "engine",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'cmake'"
},
{
"name": "compliance",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'javac'"
},
{
"name": "v2-market-stream",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'ruby'"
},
{
"name": "nfc-scanner",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'luac'"
},
{
"name": "openapi-haskell",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'ghc'"
},
{
"name": "openapi-tools",
"status": "FAIL",
"elapsed_seconds": 0,
"artifact": null,
"output": "Command not found: [Errno 2] No such file or directory: 'luac'"
}
],
"pr_note": "Include the encrypted diagnostic logd artifact(s): diagnostic/build-36b7be47.logd. The encrypted .logd is the required diagnostic content for PR review; this JSON file is metadata. Maintainers may ask you to remove these diagnostic artifacts before merging."
}
Binary file added diagnostic/build-36b7be47.logd
Binary file not shown.
16 changes: 14 additions & 2 deletions market/ws/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,27 @@ func (h *Hub) Run() {

case message := <-h.broadcast:
h.mu.RLock()
var slowClients []*Client
for client := range h.clients {
select {
case client.send <- message:
default:
close(client.send)
delete(h.clients, client)
slowClients = append(slowClients, client)
}
}
h.mu.RUnlock()

if len(slowClients) > 0 {
h.mu.Lock()
for _, client := range slowClients {
if _, ok := h.clients[client]; ok {
delete(h.clients, client)
close(client.send)
}
}
h.mu.Unlock()
h.logger.Warn("removed slow clients", zap.Int("count", len(slowClients)))
}
}
}
}
Expand Down
152 changes: 152 additions & 0 deletions market/ws/server_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
package ws

import (
"testing"
"time"

"go.uber.org/zap"
)

func TestHub_Lifecycle_Register_Unregister(t *testing.T) {
logger := zap.NewNop()
hub := NewHub(logger)

// Start hub in background
go hub.Run()

client := &Client{
hub: hub,
send: make(chan []byte, 10),
remote: "1.2.3.4:1234",
}

// 1. Register client
hub.register <- client

// Give loop time to process
time.Sleep(10 * time.Millisecond)

hub.mu.RLock()
_, exists := hub.clients[client]
hub.mu.RUnlock()
if !exists {
t.Fatalf("expected client to be registered")
}

// 2. Unregister client
hub.unregister <- client

// Give loop time to process
time.Sleep(10 * time.Millisecond)

hub.mu.RLock()
_, exists = hub.clients[client]
hub.mu.RUnlock()
if exists {
t.Fatalf("expected client to be unregistered")
}

// Verify channel is closed
_, open := <-client.send
if open {
t.Fatalf("expected client.send channel to be closed after unregister")
}
}

func TestHub_Broadcast(t *testing.T) {
logger := zap.NewNop()
hub := NewHub(logger)
go hub.Run()

client1 := &Client{
hub: hub,
send: make(chan []byte, 10),
remote: "1.2.3.4:1001",
}
client2 := &Client{
hub: hub,
send: make(chan []byte, 10),
remote: "1.2.3.4:1002",
}

hub.register <- client1
hub.register <- client2
time.Sleep(10 * time.Millisecond)

// Broadcast a message
msg := []byte("hello market")
hub.broadcast <- msg

// Verify both clients receive the broadcast message
select {
case received := <-client1.send:
if string(received) != "hello market" {
t.Errorf("client 1 received incorrect message: %s", string(received))
}
case <-time.After(100 * time.Millisecond):
t.Errorf("client 1 did not receive broadcast")
}

select {
case received := <-client2.send:
if string(received) != "hello market" {
t.Errorf("client 2 received incorrect message: %s", string(received))
}
case <-time.After(100 * time.Millisecond):
t.Errorf("client 2 did not receive broadcast")
}
}

func TestHub_SlowClientCleanup(t *testing.T) {
logger := zap.NewNop()
hub := NewHub(logger)
go hub.Run()

// Client 1 has a very small buffer of 1 and we fill it up
client1 := &Client{
hub: hub,
send: make(chan []byte, 1),
remote: "1.2.3.4:1001",
}
// Client 2 has standard buffer
client2 := &Client{
hub: hub,
send: make(chan []byte, 10),
remote: "1.2.3.4:1002",
}

hub.register <- client1
hub.register <- client2
time.Sleep(10 * time.Millisecond)

// Fill client1's buffer
client1.send <- []byte("fill")

// Broadcast should trigger default case (client1's buffer is full)
hub.broadcast <- []byte("broadcast-message")
time.Sleep(10 * time.Millisecond)

// Client 1 should be removed from hub and its send channel closed
hub.mu.RLock()
_, exists1 := hub.clients[client1]
_, exists2 := hub.clients[client2]
hub.mu.RUnlock()

if exists1 {
t.Errorf("expected client1 (slow) to be removed from clients map")
}
if !exists2 {
t.Errorf("expected client2 (active) to remain in clients map")
}

// Verify client1's channel is closed
_, open := <-client1.send
// Since we manually filled it with "fill", the first read is "fill", next is close
if open {
// Read second time (which should be close or broadcast-message if race, but channel should be closed)
_, open = <-client1.send
if open {
t.Errorf("expected client1 channel to be closed")
}
}
}
Binary file modified tools/encryptly/linux-arm64/encryptly
Binary file not shown.