Compare commits

...

12 Commits

Author SHA1 Message Date
ton 151e4e74cf update 2026-09-01 14:35:57 +07:00
ton 42b66366ae update 2026-09-01 12:21:17 +07:00
ton b0761fae75 update 2026-09-01 12:21:02 +07:00
ton f9e952e5ed update 2026-09-01 12:06:41 +07:00
ton 397885511a add eventSink 2026-09-01 12:03:50 +07:00
ton ee8ade1189 update 2026-08-31 15:52:40 +07:00
ton 20c51cf39f update 2026-08-30 10:46:39 +07:00
ton f09a53b6c3 update 2026-08-29 19:25:04 +07:00
ton c078948a7c update 2026-08-29 19:12:14 +07:00
ton 3780eb41df update 2026-08-29 18:47:45 +07:00
ton c28b7ebf84 Merge pull request 'V0.6.2' (#14) from v0.6.2 into main
Reviewed-on: #14
2026-08-29 02:58:21 +00:00
ton 27fd52fa71 Merge pull request 'V0.6.2 fix precompile' (#13) from v0.6.2-fix_precompile into v0.6.2
Reviewed-on: #13
2026-08-29 02:56:16 +00:00
3 changed files with 108 additions and 8 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
name = "GeneralUtils"
uuid = "c6c72f09-b708-4ac8-ac7c-2084d70108fe"
version = "0.6.2"
version = "0.6.9"
authors = ["tonaerospace <tonaerospace.etc@gmail.com>"]
[deps]
+5 -5
View File
@@ -46,13 +46,13 @@ https://s3-web.mydomain.com/my_bucket_name/users-1005.json
# 1. Custom GarageConfig Definition (Thread-Safe, No Global State)
# ===================================================================
struct SimpleCredentials
mutable struct SimpleCredentials
access_key_id::String
secret_key::String
token::String
end
struct GarageConfig <: AWS.AbstractAWSConfig
mutable struct GarageConfig <: AWS.AbstractAWSConfig
endpoint::String
region::String
credentials::SimpleCredentials
@@ -113,7 +113,7 @@ julia> storage = GarageStorage("https://s3-api.yiem.cc", "GKb08015", "55114ff948
GarageStorage(GarageConfig(...), "sommpanion-s3")
```
"""
struct GarageStorage
mutable struct GarageStorage
config::GarageConfig
bucket::String
end
@@ -146,7 +146,7 @@ julia> downloadUrl.web
"https://s3-web.yiem.cc/sommpanion-s3/test.json"
```
"""
struct put_file
mutable struct put_file
storage::GarageStorage
end
function (pf::put_file)(key::String, data::Union{String, Vector{UInt8}}
@@ -279,7 +279,7 @@ end
- `enabled::Bool`: Whether the rule is active (default: `true`).
- `id::String`: Unique identifier for the rule (default: auto-generated).
"""
struct LifecycleExpiration
mutable struct LifecycleExpiration
prefix::String
days::Int
enabled::Bool
+102 -2
View File
@@ -4,12 +4,12 @@ export timedifference, showstracktrace, findHighestIndexKey, uuid4snakecase, rep
findMatchingDictKey, randstring, randstrings, timeout,
dataframeToCSV, dfToVectorDict, disintegrate_vectorDict, getDataFrameValue, dfRowtoString,
dfToString, dataframe_to_json_list, dictToString, dictToString_noKey, issomething,
dictToString_numbering, extract_triple_backtick_text,
dictToString_numbering, extract_triple_backtick_text, eventSink,
countGivenWords, remove_french_accents, removestring,
extractTextBetweenCharacter, extractTextBetweenString,
convertCamelSnakeKebabCase, fitrange, recentElementsIndex, nonRecentElementsIndex
using JSON, DataStructures, Distributions, Random, Dates, UUIDs, DataFrames
using JSON, DataStructures, Distributions, Random, Dates, UUIDs, DataFrames, NATS, Dates
# ---------------------------------------------- 100 --------------------------------------------- #
@@ -1173,6 +1173,106 @@ function removestring(text::String, removelist::Vector{String})::String
end
"""
Create an event sink for logging messages and/or publishing to NATS or printing to console. File logging defaults to false.
# Fields
- `natsConn`: NATS connection, or `nothing` for file-only sink
- `topic`: NATS topic to publish to, or `nothing` for file-only sink
- `service_name`: Optional prefix added to log entries
- `log_file`: Path to the log file
- `max_log_entries`: Maximum number of entries to keep in the log file
# Callable interface
```julia
(es::eventSink)(msg::String; log=false, publish=true, console=true) -> Nothing
```
Three independent outputs — each defaults to `true` except `log`:
- `console` (default `true`) → println to stdout
- `publish` (default `true`) → publish to NATS topic (no-op if no connection)
- `log` (default `false`) → append to `log_file`
# Examples
```julia
using NATS, Dates
conn = NATS.connect("nats.yiem.cc")
# ——— With NATS (console + NATS by default) ———
es = eventSink(natsConn=conn, topic="agent.events", service_name="agent1")
es("starting up") # console + NATS
es("logged"; log=true) # console + file + NATS
es("quiet"; console=false) # NATS only
es("file+nats"; log=true, console=false) # file + NATS
es("console-only"; publish=false, log=false) # console only
# ——— File-only sink (no NATS connection) ———
es2 = eventSink(log_file="./log/eventSink2.md", service_name="worker")
es2("ready") # console only
es2("file-logged"; log=true) # console + file
es2("file-only"; log=true, console=false) # file only
es2("silent"; console=false) # nothing (no NATS, log=false, console=false)
NATS.drain(conn)
```
"""
struct eventSink
natsConn::Union{NATS.Connection, Nothing}
topic::Union{String, Nothing}
service_name::String
log_file::String
max_log_entries::Int
end
eventSink(; natsConn=nothing, topic=nothing, service_name="", log_file="./log/eventSink.md", max_log_entries=100) =
eventSink(natsConn, topic, service_name, log_file, max_log_entries)
function (es::eventSink)(msg::String; log=false, publish=true, console=true)
timestamp = Dates.format(now(), "yyyy-mm-ddTHH:MM:SS.sss")
svc_prefix = isempty(es.service_name) ? "" : "[$(es.service_name)] "
entry = "- [$timestamp] $svc_prefix$msg\n"
if console
println("[$timestamp] $svc_prefix$msg")
end
if log
log_dir = dirname(es.log_file)
mkpath(log_dir)
open(es.log_file, "a") do f
write(f, entry)
end
# Rotate after write — keep only last max_log_entries entries
content = read(es.log_file, String)
entries = split(content, r"- \[", keepempty=false)
if length(entries) > es.max_log_entries
rotate!(es)
end
end
if publish && es.topic !== nothing && es.natsConn !== nothing
try
NATS.publish(es.natsConn, es.topic, entry)
catch e
@warn "eventSink NATS publish failed" exception=e
end
end
end
"""
rotate!(es::eventSink) -> Nothing
Rewrite the log file keeping only the last `max_log_entries` entries.
Call after writing when the entry count reaches the limit.
"""
function rotate!(es::eventSink)
content = read(es.log_file, String)
entries = split(content, r"- \[", keepempty=false)
open(es.log_file, "w") do f
write(f, "- [")
for e in entries[2:end]
write(f, "- [", e)
end
end
end