Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4dad213752 | |||
| 03ff2a2626 | |||
| 712d0c891f | |||
| e28dc48bd0 |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
devdocs/*.sh text eol=lf
|
||||||
8
CLAUDE.md
Normal file
8
CLAUDE.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Sockeye — instructions for Claude Code
|
||||||
|
|
||||||
|
Sockeye is the internal licensing server for AyaNova. Its server began as a copy of AyaNova's
|
||||||
|
(`..\raven`), with some names changed: `devdocs/NAME-MAP.md` lists them, and
|
||||||
|
`devdocs/compare-with-raven.sh` compares the shared files with the names mapped. For a low-level
|
||||||
|
server fix in either codebase, check whether the other needs it too, and record the answer.
|
||||||
|
|
||||||
|
The working rules in `..\raven\CLAUDE.md` apply here as well.
|
||||||
81
devdocs/NAME-MAP.md
Normal file
81
devdocs/NAME-MAP.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
# AyaNova ↔ Sockeye name map
|
||||||
|
|
||||||
|
Sockeye's server began as a copy of AyaNova's (`raven/server/AyaNova`). Some names were
|
||||||
|
changed for Sockeye; most code is otherwise the same. Use this map to carry a fix from one
|
||||||
|
codebase to the other. Mapped 2026-10-27, AyaNova `main` (8.3.0) against Sockeye `main` (8.1.x).
|
||||||
|
|
||||||
|
`compare-with-raven.sh` (beside this file) applies the map and compares the shared files, so
|
||||||
|
only real code differences show:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash compare-with-raven.sh # every shared file: differing lines, AyaNova lines, path
|
||||||
|
bash compare-with-raven.sh util/DbUtil.cs # the diff for one file (< AyaNova mapped, > Sockeye)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Renamed
|
||||||
|
|
||||||
|
| AyaNova | Sockeye | Where |
|
||||||
|
|---|---|---|
|
||||||
|
| namespace `AyaNova.*`, `AyaNova` in text | `Sockeye.*`, `Sockeye` | everywhere |
|
||||||
|
| `AyaType` (enum) | `SockType` | `biz/AyaType.cs` → `biz/SockType.cs` |
|
||||||
|
| `AyaTypeId` | `SockTypeId` | `biz/` |
|
||||||
|
| `AyaEvent` (enum) | `SockEvent` | `biz/` |
|
||||||
|
| `AyaDaysOfWeek` (enum) | `SockDaysOfWeek` | `biz/` |
|
||||||
|
| `AyaNovaVersion` | `SockeyeVersion` | `util/` |
|
||||||
|
| `AyaNovaConnectionString`, `AyaNovaServerURL`, `logRuleAyaNovaItems` | `SockeyeConnectionString`, `SockeyeServerURL`, `logRuleSockeyeItems` | `util/` |
|
||||||
|
| `AyaTypeTranslated`, `ayaTypeColumnName` | `SockTypeTranslated`, `sockTypeColumnName` | DataList, PickList |
|
||||||
|
| stored type property `AType` (JSON `aType`) | `SockType` (JSON `sockType`) | `models/`: Attachment, Event, SearchKey, OpsJob, Report, Review, IntegrationItem, DataListSelectedRequest… |
|
||||||
|
| computed `public AyaType AyaType { get => AyaType.X; }` (JSON `ayaType`) | `public SockType SType { get => SockType.X; }` (JSON `sType`) | business models: Customer, User, Memo, Reminder, Review… |
|
||||||
|
| locals and parameters `ayaType`, `atype`, `ayId`, `ayaEvent` | `sockType`, `sockId`, `sockEvent` (a few `stype`, `sock`) | everywhere |
|
||||||
|
| database columns `atype`, `ayatype`, `ayid`, `ayevent` | `socktype`, `sockid`, `sockevent`, and `stype` on business tables | `util/AySchema.cs`, raw SQL in DataList/PickList/biz |
|
||||||
|
| config keys `AYANOVA_*` | `SOCKEYE_*`, same suffix | `util/ServerBootConfig.cs`, `config.json`, environment |
|
||||||
|
| client `src/api/ayatype.js`, `ayanova-version.js` | `src/api/socktype.js`, `sockeye-version.js` | `raven-client` ↔ `sockeye-client` |
|
||||||
|
|
||||||
|
The shared `AyaType`/`SockType` members have the same numbers (Customer 8, User 3, Report 57…),
|
||||||
|
and `AyaEvent`/`SockEvent` are identical, so stored values mean the same thing in both.
|
||||||
|
|
||||||
|
## Not renamed (same in both)
|
||||||
|
|
||||||
|
`AyContext`, `AySchema`, `AyaPickListFieldDefinition`, `AyaPickList`, `AyaField`, `AyImportData`,
|
||||||
|
`AyFileInfo`, `AyaNovaLicenseKey`; table names (`aevent`, `asearchkey`, `auser`…); routes
|
||||||
|
(`api/v{version}/…`); the folder layout (`biz`, `ControllerHelpers`, `Controllers`, `DataList`,
|
||||||
|
`generator`, `kpi`, `models`, `PickList`, `resource`, `util`).
|
||||||
|
|
||||||
|
## Only in one codebase
|
||||||
|
|
||||||
|
- **AyaNova only:** the service objects (work orders, quotes, PM, parts, inventory, units,
|
||||||
|
contracts, projects, rates, CSR, loan units, purchase orders, task groups, tax codes), their
|
||||||
|
KPIs, `License.cs` (licence check, client side), `Seeder.cs`, `ReportApiRelay.cs`,
|
||||||
|
`CoreJobLicense`, `CoreJobVersionCheck`, `CoreJobPM*`, `SuperUserDefaultPasswordRoutes`,
|
||||||
|
`CustomerContactRoutes`, and newer config keys (`AYANOVA_TRUSTED_PROXIES`,
|
||||||
|
`AYANOVA_SMTP_ACCEPT_ANY_CERTIFICATE`, `AYANOVA_REMOVE_LICENSE_FROM_DB`,
|
||||||
|
`AYANOVA_REPORT_RENDER_API_URL_OVERRIDE`). Also `AyaDayOfWeek` and `AyaUnitsOfTime` (PM).
|
||||||
|
- **Sockeye only:** licensing and sales (`KeyFactory`, `RavenKeyFactory`, `LicenseBiz`,
|
||||||
|
products, purchases, subscriptions, subscription servers and their states, trial licence
|
||||||
|
requests, vendor notifications, `GZCase`), `SockBot*` jobs, `FetchController`,
|
||||||
|
`RvfController`, `RvrController`, `AutoOrderProcessingUtil`.
|
||||||
|
|
||||||
|
## How close the shared files are (2026-10-27)
|
||||||
|
|
||||||
|
288 server files exist in both. After mapping, 156 are identical, about 55 differ by 1–10
|
||||||
|
lines, and the rest differ more, mostly because one codebase has objects the other lacks.
|
||||||
|
Low-level files that differ by more than the names, worth checking when a fix touches them:
|
||||||
|
|
||||||
|
| File | Differing lines | Main reason |
|
||||||
|
|---|---|---|
|
||||||
|
| `util/RunProgram.cs` | most | AyaNova has `RunNoShell` (backup without a shell, 8.3.0); Sockeye still has the old `Run` |
|
||||||
|
| `generator/CoreJobBackup.cs` | ~50 | same: Sockeye still passes the password in the `pg_dump` URI through a shell |
|
||||||
|
| `util/DbUtil.cs`, `util/AySchema.cs` | many | different tables; check `AdminConnectionString` and drop-and-recreate by hand |
|
||||||
|
| `DataList/DataListSqlFilterCriteriaBuilder.cs` | ~155 | filter fixes went into each separately; compare before changing either |
|
||||||
|
| `util/ServerBootConfig.cs`, `Program.cs`, `Startup.cs` | many | config keys and service wiring differ |
|
||||||
|
| `util/FileUtil.cs`, `util/StringUtil.cs`, `util/DateUtil.cs`, `generator/CoreJobNotify.cs`, `generator/CoreJobSweeper.cs`, `util/Mailer.cs` | 15–90 | partly real drift; check with the script |
|
||||||
|
|
||||||
|
Rerun the script for current numbers; this table is a snapshot.
|
||||||
|
|
||||||
|
## Carrying a fix across
|
||||||
|
|
||||||
|
1. Make and test the fix in one codebase.
|
||||||
|
2. Run `bash compare-with-raven.sh <file>` on each file touched: if the file matches apart from
|
||||||
|
names, the same change applies with the names above.
|
||||||
|
3. Record in both repos whether the fix applies (done, n/a, or deferred). In AyaNova that is
|
||||||
|
`raven/devdocs/modernization/NET10-PORT.md`.
|
||||||
38
devdocs/compare-with-raven.sh
Normal file
38
devdocs/compare-with-raven.sh
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Compare Sockeye server source with AyaNova's (raven) after mapping AyaNova's names to
|
||||||
|
# Sockeye's (see NAME-MAP.md), so only real code differences show.
|
||||||
|
#
|
||||||
|
# bash compare-with-raven.sh one line per shared file: differing lines, raven lines, path
|
||||||
|
# bash compare-with-raven.sh util/DbUtil.cs the diff for one file (raven mapped < > sockeye)
|
||||||
|
#
|
||||||
|
# Read-only. Expects the repos side by side under one folder (C:\data\code).
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
here="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
R="$here/../../raven/server/AyaNova"
|
||||||
|
S="$here/../server"
|
||||||
|
|
||||||
|
# AyaNova name -> Sockeye name; order matters (longer names first)
|
||||||
|
norm() {
|
||||||
|
sed -E \
|
||||||
|
-e 's/AyaNovaVersion/SockeyeVersion/g' \
|
||||||
|
-e 's/AyaNova/Sockeye/g; s/ayanova/sockeye/g; s/AYANOVA_/SOCKEYE_/g' \
|
||||||
|
-e 's/public AyaType AyaType/public SockType SType/g' \
|
||||||
|
-e 's/AyaTypeId/SockTypeId/g; s/AyaType/SockType/g; s/ayaType/sockType/g; s/ayatype/socktype/g' \
|
||||||
|
-e 's/\bAType\b/SockType/g; s/\batype\b/socktype/g' \
|
||||||
|
-e 's/AyaEvent/SockEvent/g; s/ayaEvent/sockEvent/g; s/ayevent/sockevent/g' \
|
||||||
|
-e 's/AyaDaysOfWeek/SockDaysOfWeek/g' \
|
||||||
|
-e 's/\bAyId\b/SockId/g; s/\bayId\b/sockId/g; s/\bayid\b/sockid/g' \
|
||||||
|
"$1" | tr -d '\r'
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ $# -gt 0 ]; then
|
||||||
|
diff <(norm "$R/$1") <(tr -d '\r' < "$S/$1") || true
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
(cd "$R" && find . -name '*.cs' -not -path './obj/*' -not -path './bin/*') | sort | while read -r f; do
|
||||||
|
[ -f "$S/$f" ] || continue
|
||||||
|
d=$(diff <(norm "$R/$f") <(tr -d '\r' < "$S/$f") | grep -c '^[<>]' || true)
|
||||||
|
echo "$d $(wc -l < "$R/$f") ${f#./}"
|
||||||
|
done
|
||||||
@@ -51,22 +51,36 @@ namespace Sockeye.Util
|
|||||||
internal static void SetNextBackup()
|
internal static void SetNextBackup()
|
||||||
{
|
{
|
||||||
DateTime utcNow = DateTime.UtcNow;
|
DateTime utcNow = DateTime.UtcNow;
|
||||||
|
//case 4682: the backup time is a time on the server's clock; days are the server's local days
|
||||||
|
DateTime localToday = TimeZoneInfo.ConvertTimeFromUtc(utcNow, TimeZoneInfo.Local).Date;
|
||||||
//Has last backup run more than 24 hours ago?
|
//Has last backup run more than 24 hours ago?
|
||||||
if (NextBackup < utcNow.AddHours(-24))
|
if (NextBackup < utcNow.AddHours(-24))
|
||||||
{
|
{
|
||||||
//set it to today then
|
//set it to today then
|
||||||
NextBackup = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, Backup.BackupTime.Hour, Backup.BackupTime.Minute, 0, DateTimeKind.Utc);
|
NextBackup = BackupTimeOnLocalDay(localToday);
|
||||||
//Make sure next backup is in the future
|
//Make sure next backup is in the future
|
||||||
if (NextBackup < utcNow)
|
if (NextBackup < utcNow)
|
||||||
NextBackup = NextBackup.AddDays(1);
|
NextBackup = BackupTimeOnLocalDay(localToday.AddDays(1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//less than 24 hours, set it to tomorrow
|
//less than 24 hours, set it to tomorrow
|
||||||
NextBackup = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, Backup.BackupTime.Hour, Backup.BackupTime.Minute, 0, DateTimeKind.Utc);
|
NextBackup = BackupTimeOnLocalDay(localToday.AddDays(1));
|
||||||
NextBackup = NextBackup.AddDays(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//case 4682: the backup time is stored as the UTC moment it meant on the day it was set, and was run at that UTC hour
|
||||||
|
//every day, so it moved an hour on the server's clock with each daylight saving change. The server's clock time is
|
||||||
|
//recovered with that day's offset and the backup is run at that clock time on the given local day (UTC returned)
|
||||||
|
private static DateTime BackupTimeOnLocalDay(DateTime localDay)
|
||||||
|
{
|
||||||
|
var chosen = TimeZoneInfo.ConvertTimeFromUtc(DateTime.SpecifyKind(Backup.BackupTime, DateTimeKind.Utc), TimeZoneInfo.Local);
|
||||||
|
var local = DateTime.SpecifyKind(localDay.Date + new TimeSpan(chosen.Hour, chosen.Minute, 0), DateTimeKind.Unspecified);
|
||||||
|
//a time skipped when the clocks go forward (e.g. 2:30 AM that night) runs an hour later
|
||||||
|
if (TimeZoneInfo.Local.IsInvalidTime(local))
|
||||||
|
local = local.AddHours(1);
|
||||||
|
return TimeZoneInfo.ConvertTimeToUtc(local, TimeZoneInfo.Local);
|
||||||
|
}
|
||||||
|
|
||||||
}//eoc
|
}//eoc
|
||||||
}//eons
|
}//eons
|
||||||
Reference in New Issue
Block a user