Skip to content
Merged
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
18 changes: 10 additions & 8 deletions engine/UPSTREAM.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,27 @@
**9,621**(对照 `f4c50506`)、**9,659**(对照 `be48afbe`),生产 3,852、
测试 5,758。

2026-11-12 的 ports、killer、groups 与 cmd 重写在此基础上继续下降:对照
`26dbcae` 为 **6,307** 行 / 410 段,分布在 75 个文件(生产 2,305、测试 4,002)。
2026-11-12 的 ports、killer、groups、cmd、scanner 与 store 重写在此基础上继续
下降:对照 `26dbcae` 为 **5,530** 行 / 328 段,分布在 60 个文件(生产 2,073、
测试 3,457)。只有 `internal/daemon` 仍有复制段。

按包(对照 `26dbcae`,ports、killer、groups 与 cmd 重写后):
按包(对照 `26dbcae`,除 daemon 外已重写):

| 包 | 生产 | 测试 | 合计 |
| --- | ---: | ---: | ---: |
| `internal/daemon` | 2,073 | 3,457 | 5,530 |
| `internal/cmd` | 0 | 0 | 0 |
| `internal/groups` | 0 | 0 | 0 |
| `internal/scanner` | 220 | 540 | 760 |
| `internal/scanner` | 0 | 0 | 0 |
| `internal/ports` | 0 | 0 | 0 |
| `internal/killer` | 0 | 0 | 0 |
| `internal/store` | 12 | 5 | 17 |
| `internal/store` | 0 | 0 | 0 |

`internal/claims`、`internal/cmd`、`internal/display`、`internal/testenv`、
`internal/groups`、`internal/ports`、`internal/killer` 与
`internal/store/claims*.go` 已经归零;`internal/docker` 只剩结构体字段与表驱动
用例数据。`internal/store` 已整包重写:生产代码从 1,076 行降到 199 行。
`internal/groups`、`internal/killer`、`internal/ports`、`internal/scanner`、
`internal/store` 与 `internal/store/claims*.go` 已经归零;`internal/docker` 只剩
结构体字段与表驱动用例数据。`internal/store` 已整包重写:生产代码从 1,076 行降到
199 行。

```sh
git clone https://github.com/raskrebs/sonar /tmp/sonar
Expand Down
47 changes: 29 additions & 18 deletions engine/internal/scanner/attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,25 @@ type attribution struct {
identities map[string]string
}

// SetStore installs the store after construction. The daemon does it from
// Serve, once the database is open; a nil store leaves the loop unpersisted.
// SetStore installs the store after construction. The daemon calls it from
// Serve once the database is open; leaving the store nil keeps the loop
// unpersisted.
func (l *Loop) SetStore(s Store) {
if s == nil {
return
}
l.attr.mu.Lock()
defer l.attr.mu.Unlock()
l.adoptStoreLocked(s)
}

// adoptStoreLocked points the loop at s and forgets everything cached from the
// store it used before: acknowledgements and identity rows belong to the store
// that recorded them, not to the one replacing it. Caller holds the attribution
// lock.
func (l *Loop) adoptStoreLocked(s Store) {
l.opts.Store = s
l.attr.seeded = false
// Acknowledgements and identity rows belong to this store, not the last one.
l.attr.roots = make(map[string]bool)
l.attr.identities = make(map[string]string)
}
Expand Down Expand Up @@ -343,22 +351,22 @@ func (l *Loop) loadAliases(st Store) {
l.attr.index.SetAliases(nil)
return
}
aliases, err := st.GroupAliases()
names, err := st.GroupAliases()
if err != nil {
l.opts.Logger.Warn("reading project aliases", "error", err)
return
}
l.attr.index.SetAliases(aliases)
l.attr.index.SetAliases(names)
}

// registry is the run registry to attribute with: the one `oberth start`
// installed, or the attribution the scanner already put on the port itself.
// installed, or else the attribution the scanner already put on the port
// itself.
func (l *Loop) registry() groups.Registry {
if l.opts.Runs == nil {
return groups.PortRuns{}
}
if r := l.opts.Runs(); r != nil {
return r
if l.opts.Runs != nil {
if r := l.opts.Runs(); r != nil {
return r
}
}
return groups.PortRuns{}
}
Expand Down Expand Up @@ -463,9 +471,9 @@ func (l *Loop) recordIdentityRoot(st Store, root string) {
l.attr.identities[identity] = ""
}

// record writes the port transitions of one published delta to the history
// ring. Only the three port-scoped kinds are persisted; health_changed and
// scan_error stay in-memory notifications.
// record writes the port transitions of one published delta into the history
// ring. Just the three port-scoped kinds are persisted; health_changed and
// scan_error remain in-memory notifications.
func (l *Loop) record(events []state.Event) {
st := l.store()
if st == nil || len(events) == 0 {
Expand Down Expand Up @@ -514,16 +522,19 @@ func historyRow(ev state.Event, at time.Time) (store.HistoryEvent, bool) {
}, true
}

// store returns the installed store under the attribution lock.
// store hands back the installed store while holding the attribution lock.
func (l *Loop) store() Store {
l.attr.mu.Lock()
defer l.attr.mu.Unlock()
return l.opts.Store
}

// eventTime parses an RFC 3339 timestamp, falling back to the caller's instant
// when the field is missing or malformed.
func eventTime(at string, fallback time.Time) time.Time {
if t, err := time.Parse(time.RFC3339, at); err == nil {
return t
parsed, err := time.Parse(time.RFC3339, at)
if err != nil {
return fallback
}
return fallback
return parsed
}
Loading
Loading