zenbook migration

This commit is contained in:
2026-02-08 10:25:39 +01:00
commit 84b8735385
178 changed files with 5350 additions and 0 deletions
+13
View File
@@ -0,0 +1,13 @@
module test
go 1.23.1
require (
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/go-faker/faker/v4 v4.5.0 // indirect
github.com/google/uuid v1.5.0 // indirect
github.com/oapi-codegen/runtime v1.1.1 // indirect
github.com/sony/gobreaker v0.5.0 // indirect
github.com/typesense/typesense-go/v2 v2.0.0 // indirect
golang.org/x/text v0.21.0 // indirect
)
+22
View File
@@ -0,0 +1,22 @@
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-faker/faker/v4 v4.5.0 h1:ARzAY2XoOL9tOUK+KSecUQzyXQsUaZHefjyF8x6YFHc=
github.com/go-faker/faker/v4 v4.5.0/go.mod h1:p3oq1GRjG2PZ7yqeFFfQI20Xm61DoBDlCA8RiSyZ48M=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg=
github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/typesense/typesense-go/v2 v2.0.0 h1:+MksOnrVioDqsGpz8RXkOUqhVN+yFxZwJlGDQHr/64I=
github.com/typesense/typesense-go/v2 v2.0.0/go.mod h1:7V1ZBSfmdciL6yb2bPtWha+W53gV5WZhyOSpVgDJfao=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
+205
View File
@@ -0,0 +1,205 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Typesense Cluster Test</title>
<script src="https://cdn.jsdelivr.net/npm/typesense@1/dist/typesense.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
padding: 0;
}
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
margin: 20px 0;
}
.column {
border: 1px solid #eee;
padding: 15px;
border-radius: 8px;
}
.record {
border: 1px solid #ddd;
padding: 10px;
margin: 10px 0;
border-radius: 4px;
background-color: white;
}
button {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
}
button:hover {
background-color: #45a049;
}
.column-header {
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 2px solid #eee;
}
.error-message {
color: red;
margin: 10px 0;
}
</style>
</head>
<body>
<h1>Typesense Cluster Test Page</h1>
<div>
<button onclick="addRecord()">Add Random Record</button>
<button onclick="loadAllRecords()">Refresh All</button>
</div>
<div class="container">
<div class="column">
<div class="column-header">
<h2>Node 1</h2>
<div class="error-message" id="error1"></div>
</div>
<div id="records1"></div>
</div>
<div class="column">
<div class="column-header">
<h2>Node 2</h2>
<div class="error-message" id="error2"></div>
</div>
<div id="records2"></div>
</div>
<div class="column">
<div class="column-header">
<h2>Node 3</h2>
<div class="error-message" id="error3"></div>
</div>
<div id="records3"></div>
</div>
</div>
<script>
// Configuration - Replace these values with your actual Typesense cluster nodes
const TYPESENSE_NODES = [
'node-stable-1.db.typesenseha.zerops',
'node-stable-2.db.typesenseha.zerops',
'node-stable-3.db.typesenseha.zerops'
];
const TYPESENSE_PROTOCOL = 'http';
const TYPESENSE_APIKEY = 'I.GQrM0XjqokPFr729Eqo6d8ahvMYp8G';
// Initialize Typesense clients for each node
const clients = TYPESENSE_NODES.map(host => new Typesense.Client({
nodes: [{
host: host,
protocol: TYPESENSE_PROTOCOL,
port: 8108,
}],
apiKey: TYPESENSE_APIKEY,
connectionTimeoutSeconds: 3
}));
// Function to add a random record (using the first node)
// async function addRecord() {
// try {
// const record = {
// num_employees: Math.floor(Math.random() * 1000) + 1,
// created: new Date().toISOString(),
// unix: Math.floor(Date.now() / 1000)
// };
// const response = await clients[0].collections('companies').documents().create(record);
// console.log('Record added:', response);
// loadAllRecords();
// } catch (error) {
// console.error('Error adding record:', error);
// document.getElementById('error1').textContent = 'Error adding record: ' + error.message;
// }
// }
// Utility function for delay
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
// Function to add a random record to a random node
async function addRecord() {
try {
// Choose random node
const randomNodeIndex = Math.floor(Math.random() * clients.length);
const selectedClient = clients[randomNodeIndex];
const record = {
num_employees: Math.floor(Math.random() * 1000) + 1,
created: new Date().toLocaleTimeString('en-US', { hour12: false }),
unix: Math.floor(Date.now() / 1000)
};
// Clear previous errors
for (let i = 0; i < clients.length; i++) {
document.getElementById(`error${i + 1}`).textContent = '';
}
// Show which node we're writing to
document.getElementById(`error${randomNodeIndex + 1}`).textContent =
'✍️ Writing new record to this node...';
const response = await selectedClient.collections('companies').documents().create(record);
console.log(`Record added to node ${randomNodeIndex + 1}:`, response);
// Wait for 1 second before refreshing
await delay(1000);
// Clear the writing message
document.getElementById(`error${randomNodeIndex + 1}`).textContent = '';
// Refresh all nodes
loadAllRecords();
} catch (error) {
console.error('Error adding record:', error);
document.getElementById(`error${randomNodeIndex + 1}`).textContent =
'Error adding record: ' + error.message;
}
}
// Function to load records from a specific node
async function loadRecords(clientIndex) {
try {
document.getElementById(`error${clientIndex + 1}`).textContent = '';
const searchParameters = {
q: '*',
sort_by: 'unix:desc',
per_page: 100
};
const response = await clients[clientIndex].collections('companies').documents().search(searchParameters);
const recordsDiv = document.getElementById(`records${clientIndex + 1}`);
recordsDiv.innerHTML = response.hits.map(hit => `
<div class="record">
<div>ID: ${hit.document.id}</div>
<div>Employees: ${hit.document.num_employees}</div>
<div>Created: ${hit.document.created}</div>
<div>Unix Timestamp: ${hit.document.unix}</div>
</div>
`).join('');
} catch (error) {
console.error(`Error loading records from node ${clientIndex + 1}:`, error);
document.getElementById(`error${clientIndex + 1}`).textContent =
`Error loading records from node ${clientIndex + 1}: ${error.message}`;
}
}
// Function to load records from all nodes
function loadAllRecords() {
for (let i = 0; i < clients.length; i++) {
loadRecords(i);
}
}
// Load records when the page loads
loadAllRecords();
</script>
</body>
</html>
+102
View File
@@ -0,0 +1,102 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Typesense Test</title>
<script src="https://cdn.jsdelivr.net/npm/typesense@1/dist/typesense.min.js"></script>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 20px auto;
padding: 0 20px;
}
.record {
border: 1px solid #ddd;
padding: 10px;
margin: 10px 0;
border-radius: 4px;
}
button {
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
</style>
</head>
<body>
<h1>Typesense Test Page</h1>
<button onclick="addRecord()">Add Random Record</button>
<h2>Last 100 Records</h2>
<div id="records"></div>
<script>
// Configuration - Replace these values with your actual Typesense details
const TYPESENSE_HOST = 'typesense-13-8108.app-ranpu.zerops.dev';
const TYPESENSE_PROTOCOL = 'https';
const TYPESENSE_APIKEY = 'BXCkhnEpwW1Kq0nVcvcWDRtZ75aIXtYy';
// Initialize Typesense client
const client = new Typesense.Client({
nodes: [{
host: TYPESENSE_HOST,
protocol: TYPESENSE_PROTOCOL,
}],
apiKey: TYPESENSE_APIKEY,
connectionTimeoutSeconds: 3
});
// Function to add a random record
async function addRecord() {
try {
const record = {
num_employees: Math.floor(Math.random() * 1000) + 1,
created: new Date().toISOString(),
unix: Math.floor(Date.now() / 1000)
};
const response = await client.collections('companies').documents().create(record);
console.log('Record added:', response);
loadRecords(); // Refresh the list
} catch (error) {
console.error('Error adding record:', error);
}
}
// Function to load and display records
async function loadRecords() {
try {
const searchParameters = {
q: '*',
sort_by: 'unix:desc',
per_page: 100
};
const response = await client.collections('companies').documents().search(searchParameters);
const recordsDiv = document.getElementById('records');
recordsDiv.innerHTML = response.hits.map(hit => `
<div class="record">
<div>ID: ${hit.document.id}</div>
<div>Employees: ${hit.document.num_employees}</div>
<div>Created: ${hit.document.created}</div>
<div>Unix Timestamp: ${hit.document.unix}</div>
</div>
`).join('');
} catch (error) {
console.error('Error loading records:', error);
}
}
// Load records when the page loads
loadRecords();
</script>
</body>
</html>
+156
View File
@@ -0,0 +1,156 @@
package main
import (
"context"
"flag"
"fmt"
"math/rand/v2"
"os/signal"
"syscall"
"time"
"github.com/typesense/typesense-go/v2/typesense"
"github.com/typesense/typesense-go/v2/typesense/api"
"github.com/typesense/typesense-go/v2/typesense/api/pointer"
)
func main() {
if err := run(); err != nil {
panic(err)
}
}
func run() error {
var url, apiKey string
var list, del bool
var delay time.Duration
flag.StringVar(&url, "url", "url", "url")
flag.StringVar(&apiKey, "api-key", "nope", "api key")
flag.BoolVar(&list, "list", false, "whether to list 10 latest documents from collection")
flag.BoolVar(&del, "delete", false, "whether delete collection")
flag.DurationVar(&delay, "delay", time.Second, "delay between requests")
flag.Parse()
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
client := typesense.NewClient(
typesense.WithServer(url),
typesense.WithAPIKey(apiKey),
)
{
ok, err := client.Health(ctx, 5*time.Second)
if err != nil {
return err
}
if !ok {
return fmt.Errorf("health check failed")
}
}
const collectionName = "companies"
if del {
_, err := client.Collection(collectionName).Delete(ctx)
if err != nil {
return err
}
fmt.Printf("deleted collection: %s\n", collectionName)
time.Sleep(3 * time.Second)
}
var exists bool
{
collections, err := client.Collections().Retrieve(ctx)
if err != nil {
return err
}
for _, collection := range collections {
fmt.Printf("listed collection: %s\n", collection.Name)
if collection.Name == collectionName {
exists = true
}
}
}
if !exists {
collection, err := client.Collections().Create(ctx, &api.CollectionSchema{
Name: "companies",
Fields: []api.Field{
{
Name: "num_employees",
Type: "int32",
},
{
Name: "created",
Type: "string",
},
{
Name: "unix",
Type: "int64",
},
},
DefaultSortingField: pointer.String("unix"),
})
if err != nil {
return err
}
fmt.Printf("created collection: %s\n", collection.Name)
time.Sleep(3 * time.Second)
}
if list {
search, err := client.Collection(collectionName).Documents().Search(ctx, &api.SearchCollectionParams{
Q: pointer.String("*"),
Limit: pointer.Int(250),
SortBy: pointer.String("unix:desc"),
})
if err != nil {
return err
}
for i := range *search.Hits {
hit := (*search.Hits)[len(*search.Hits)-1-i]
doc := *hit.Document
fmt.Printf("LIST: ==> %s (%s)\n", doc["created"], doc["id"])
}
}
for {
if ctx.Err() != nil {
fmt.Println("context canceled")
return nil
}
now := time.Now()
document := map[string]any{
"num_employees": rand.Int32N(10000),
"created": now.Format(time.TimeOnly),
"unix": now.Unix(),
}
var id string
documentResponse, err := client.Collection(collectionName).Documents().Create(ctx, document)
if err != nil {
fmt.Printf("create document failed: %v\n", err)
continue
}
fmt.Printf("%s ==>\n", document["created"])
id = documentResponse["id"].(string)
for {
documentResponse, err = client.Collection(collectionName).Document(id).Retrieve(ctx)
if err != nil {
if ctx.Err() != nil {
fmt.Println("context canceled")
return nil
}
time.Sleep(100 * time.Millisecond)
continue
}
fmt.Printf("==> %s (%s)\n", documentResponse["created"], documentResponse["id"])
break
}
time.Sleep(delay)
}
}
+1
View File
@@ -0,0 +1 @@
node-stable-1.runtime.typesense.zerops:8107:8108,node-stable-2.runtime.typesense.zerops;:8107:8108,node-stable-3.runtime.typesense.zerops;:8107:8108
+5
View File
@@ -0,0 +1,5 @@
[server]
api-key = test
data-dir = /var/lib/typesense
;nodes = node-list.txt
+9
View File
@@ -0,0 +1,9 @@
services:
- hostname: elasticsearch
type: elasticsearch@8.16
mode: NON_HA
enableSubdomainAccess: true
- hostname: typesense
type: typesense@27.1
mode: NON_HA
enableSubdomainAccess: true
+20
View File
@@ -0,0 +1,20 @@
zerops:
- setup: typesense
build:
buildCommands:
- curl -O https://dl.typesense.org/releases/27.1/typesense-server-27.1-linux-amd64.tar.gz
- tar -xzf typesense-server-27.1-linux-amd64.tar.gz
deployFiles:
- typesense-server
- typesense-server.ini
run:
ports:
- port: 8107
description: "peering"
- port: 8108
httpSupport: true
description: "api"
initCommands:
- sudo mkdir -p /var/lib/typesense
start: zsc noop
# start: sudo /var/www/typesense-server --config=/var/www/typesense-server.ini