Skip to content

Commit 3804e8d

Browse files
committed
feat: merge master and resolve conflicts
- Resolved conflicts in DEVELOPMENT_PLAN.md by combining Phase 6 completion status - Resolved conflicts in Program.cs by integrating CORS configuration into master structure - Maintained frontend integration capabilities while keeping proper error handling and service structure
2 parents 2a9a32b + 07d44ce commit 3804e8d

18 files changed

+1731
-84
lines changed

DEVELOPMENT_PLAN.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ You can effectively work on **up to 6 parallel worktrees** without conflicts:
125125
|-------|----------|------|-------------|----------|---------|
126126
| #27 | P1 | 1d | 15-minute rollup job | 3 |**COMPLETE** |
127127
| #28 | P2 | 4-6h | Daily rollup job | 3 |**COMPLETE** |
128-
| #29 | P2 | 4-6h | Prune tool for raw data | 3 | 🔓 **UNLOCKED** |
128+
| #29 | P2 | 4-6h | Prune tool for raw data | 3 | **COMPLETE** |
129129

130130
### PHASE 6: Frontend Core (Week 2-3, Parallel) ✅ **COMPLETE**
131131
**UI foundation - EPIC #7**
@@ -166,9 +166,9 @@ You can effectively work on **up to 6 parallel worktrees** without conflicts:
166166

167167
| Issue | Priority | Time | Description | Worktree |
168168
|-------|----------|------|-------------|----------|
169-
| #23 | P1 | 1d | Windows service host wrapper | 1 |
170-
| ENV-15 | P1 | 1d | Installer conventions, paths | 1 |
171-
| #24 | P1 | 4-6h | Inno Setup installer script | 1 |
169+
| #23 | P1 | 1d | **COMPLETE** - Windows service host wrapper | 1 |
170+
| ENV-15 | P1 | 1d | **COMPLETE** - Installer conventions, paths | 1 |
171+
| #24 | P1 | 4-6h | Inno Setup installer script | ✅ Complete |
172172

173173
### PHASE 8: Quality & Polish (Week 4)
174174
**Non-critical enhancements**
@@ -250,7 +250,7 @@ git worktree remove ../pulse-env-setup
250250
- **Phase 2**: ✅ **COMPLETE** - Database created, migrations run, config storage & settings implemented with full testing
251251
- **Phase 3**: ✅ **COMPLETE** - Can detect UP/DOWN state changes with continuous monitoring, outage tracking, and concurrent probe execution
252252
- **Phase 4**: ✅ **COMPLETE** - All 4 API endpoints implemented and tested: live status, history, config apply, and config versions.
253-
- **Phase 5**: ✅ **COMPLETE** - Issues #27 and #28 complete: 15-minute and daily rollups computed automatically every 5 minutes with watermark tracking
253+
- **Phase 5**: ✅ **COMPLETE** - Issues #27, #28, and #29 complete: 15-minute and daily rollups computed automatically every 5 minutes with watermark tracking, plus configurable raw data pruning with 60-day default retention
254254
- **Phase 6**: ✅ **COMPLETE** - UI loads, shows live status with real-time updates from backend, CORS integration working
255255
- **Phase 7**: Service installs and runs
256256
- **Phase 8**: All tests pass, code quality gates met

README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,50 @@ npm run dev
5353
- **[Data Model](./docs/data-model.cs)** - Entity Framework Core entities
5454
- **[Rollup Algorithms](./docs/rollup-spec.md)** - Data aggregation specifications
5555

56+
## Installation & Deployment
57+
58+
### Windows Installer
59+
60+
Build and create a professional Windows installer:
61+
62+
```bash
63+
# Build installer (includes build and packaging)
64+
.\build-installer.ps1
65+
66+
# Build installer without rebuilding (faster for testing)
67+
.\build-installer.ps1 -SkipBuild
68+
69+
# Open installer directory after build
70+
.\build-installer.ps1 -OpenInstaller
71+
```
72+
73+
The installer will:
74+
- Install to `Program Files\ThingConnect.Pulse`
75+
- Create data directories in `ProgramData\ThingConnect.Pulse`
76+
- Register and start `ThingConnectPulseSvc` Windows service
77+
- Create Start Menu shortcuts
78+
- Ask before deleting data on uninstall
79+
80+
### Development Installation
81+
82+
For development and testing:
83+
84+
```bash
85+
# Install as Windows service (development)
86+
.\install-service.ps1 install
87+
88+
# Manage service
89+
.\install-service.ps1 start|stop|status
90+
91+
# Uninstall service
92+
.\install-service.ps1 uninstall
93+
```
94+
95+
### Documentation
96+
97+
- **[Installer Conventions](./docs/installer-map.md)** - Windows service installation specification
98+
- **[Logging Configuration](./docs/logging.md)** - Structured logging setup and policies
99+
56100
## API Endpoints
57101

58102
The server provides REST API endpoints for configuration management and monitoring data:
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
using Microsoft.AspNetCore.Mvc;
2+
using ThingConnect.Pulse.Server.Services.Prune;
3+
4+
namespace ThingConnect.Pulse.Server.Controllers;
5+
6+
/// <summary>
7+
/// Test controller for prune functionality (development only)
8+
/// </summary>
9+
[ApiController]
10+
[Route("api/test/prune")]
11+
public sealed class TestPruneController : ControllerBase
12+
{
13+
private readonly IPruneService _pruneService;
14+
private readonly ILogger<TestPruneController> _logger;
15+
16+
public TestPruneController(IPruneService pruneService, ILogger<TestPruneController> logger)
17+
{
18+
_pruneService = pruneService;
19+
_logger = logger;
20+
}
21+
22+
/// <summary>
23+
/// Get current retention period
24+
/// </summary>
25+
[HttpGet("retention-days")]
26+
public async Task<IActionResult> GetRetentionDaysAsync()
27+
{
28+
try
29+
{
30+
var days = await _pruneService.GetRetentionDaysAsync();
31+
return Ok(new { retentionDays = days });
32+
}
33+
catch (Exception ex)
34+
{
35+
_logger.LogError(ex, "Error getting retention days");
36+
return StatusCode(500, new { message = "Error getting retention days", error = ex.Message });
37+
}
38+
}
39+
40+
/// <summary>
41+
/// Set retention period in days
42+
/// </summary>
43+
[HttpPost("retention-days/{days:int}")]
44+
public async Task<IActionResult> SetRetentionDaysAsync(int days)
45+
{
46+
try
47+
{
48+
if (days <= 0)
49+
{
50+
return BadRequest(new { message = "Retention days must be greater than 0" });
51+
}
52+
53+
await _pruneService.SetRetentionDaysAsync(days);
54+
return Ok(new { message = $"Retention period set to {days} days" });
55+
}
56+
catch (Exception ex)
57+
{
58+
_logger.LogError(ex, "Error setting retention days to {Days}", days);
59+
return StatusCode(500, new { message = "Error setting retention days", error = ex.Message });
60+
}
61+
}
62+
63+
/// <summary>
64+
/// Dry-run prune operation - shows what would be deleted without actually deleting
65+
/// </summary>
66+
[HttpPost("dry-run")]
67+
public async Task<IActionResult> DryRunPruneAsync()
68+
{
69+
try
70+
{
71+
_logger.LogInformation("Manual dry-run prune requested");
72+
var wouldDeleteCount = await _pruneService.PruneRawDataAsync(dryRun: true);
73+
var retentionDays = await _pruneService.GetRetentionDaysAsync();
74+
75+
return Ok(new
76+
{
77+
message = "Dry-run prune completed",
78+
wouldDeleteCount = wouldDeleteCount,
79+
retentionDays = retentionDays,
80+
cutoffDate = DateTimeOffset.UtcNow.AddDays(-retentionDays).ToString("O")
81+
});
82+
}
83+
catch (Exception ex)
84+
{
85+
_logger.LogError(ex, "Error during dry-run prune");
86+
return StatusCode(500, new { message = "Error during dry-run prune", error = ex.Message });
87+
}
88+
}
89+
90+
/// <summary>
91+
/// Execute actual prune operation - PERMANENTLY deletes old raw data
92+
/// </summary>
93+
[HttpPost("execute")]
94+
public async Task<IActionResult> ExecutePruneAsync()
95+
{
96+
try
97+
{
98+
_logger.LogInformation("Manual prune execution requested");
99+
var deletedCount = await _pruneService.PruneRawDataAsync(dryRun: false);
100+
var retentionDays = await _pruneService.GetRetentionDaysAsync();
101+
102+
return Ok(new
103+
{
104+
message = "Prune operation completed successfully",
105+
deletedCount = deletedCount,
106+
retentionDays = retentionDays
107+
});
108+
}
109+
catch (Exception ex)
110+
{
111+
_logger.LogError(ex, "Error during prune execution");
112+
return StatusCode(500, new { message = "Error during prune execution", error = ex.Message });
113+
}
114+
}
115+
}

ThingConnect.Pulse.Server/Data/SeedData.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public static void Initialize(PulseDbContext context)
106106
Id = "test-config-001",
107107
AppliedTs = now,
108108
FileHash = "abcd1234",
109-
FilePath = @"C:\ProgramData\ThingConnect.Pulse\config.yaml",
109+
FilePath = @"C:\ProgramData\ThingConnect.Pulse\config\config.yaml",
110110
Actor = "system",
111111
Note = "Initial test configuration"
112112
};

0 commit comments

Comments
 (0)