You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.9 KiB
145 lines
3.9 KiB
/** |
|
* Copyright 2017 Confluent Inc. |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
package kafka |
|
|
|
import ( |
|
"fmt" |
|
"strconv" |
|
) |
|
|
|
/* |
|
#include <stdlib.h> |
|
#include "select_rdkafka.h" |
|
|
|
static int64_t _c_rdkafka_offset_tail(int64_t rel) { |
|
return RD_KAFKA_OFFSET_TAIL(rel); |
|
} |
|
*/ |
|
import "C" |
|
|
|
// Offset type (int64) with support for canonical names |
|
type Offset int64 |
|
|
|
// OffsetBeginning represents the earliest offset (logical) |
|
const OffsetBeginning = Offset(C.RD_KAFKA_OFFSET_BEGINNING) |
|
|
|
// OffsetEnd represents the latest offset (logical) |
|
const OffsetEnd = Offset(C.RD_KAFKA_OFFSET_END) |
|
|
|
// OffsetInvalid represents an invalid/unspecified offset |
|
const OffsetInvalid = Offset(C.RD_KAFKA_OFFSET_INVALID) |
|
|
|
// OffsetStored represents a stored offset |
|
const OffsetStored = Offset(C.RD_KAFKA_OFFSET_STORED) |
|
|
|
func (o Offset) String() string { |
|
switch o { |
|
case OffsetBeginning: |
|
return "beginning" |
|
case OffsetEnd: |
|
return "end" |
|
case OffsetInvalid: |
|
return "unset" |
|
case OffsetStored: |
|
return "stored" |
|
default: |
|
return fmt.Sprintf("%d", int64(o)) |
|
} |
|
} |
|
|
|
// Set offset value, see NewOffset() |
|
func (o *Offset) Set(offset interface{}) error { |
|
n, err := NewOffset(offset) |
|
|
|
if err == nil { |
|
*o = n |
|
} |
|
|
|
return err |
|
} |
|
|
|
// NewOffset creates a new Offset using the provided logical string, or an |
|
// absolute int64 offset value. |
|
// Logical offsets: "beginning", "earliest", "end", "latest", "unset", "invalid", "stored" |
|
func NewOffset(offset interface{}) (Offset, error) { |
|
|
|
switch v := offset.(type) { |
|
case string: |
|
switch v { |
|
case "beginning": |
|
fallthrough |
|
case "earliest": |
|
return Offset(OffsetBeginning), nil |
|
|
|
case "end": |
|
fallthrough |
|
case "latest": |
|
return Offset(OffsetEnd), nil |
|
|
|
case "unset": |
|
fallthrough |
|
case "invalid": |
|
return Offset(OffsetInvalid), nil |
|
|
|
case "stored": |
|
return Offset(OffsetStored), nil |
|
|
|
default: |
|
off, err := strconv.Atoi(v) |
|
return Offset(off), err |
|
} |
|
|
|
case int: |
|
return Offset((int64)(v)), nil |
|
case int64: |
|
return Offset(v), nil |
|
default: |
|
return OffsetInvalid, newErrorFromString(ErrInvalidArg, |
|
fmt.Sprintf("Invalid offset type: %t", v)) |
|
} |
|
} |
|
|
|
// OffsetTail returns the logical offset relativeOffset from current end of partition |
|
func OffsetTail(relativeOffset Offset) Offset { |
|
return Offset(C._c_rdkafka_offset_tail(C.int64_t(relativeOffset))) |
|
} |
|
|
|
// offsetsForTimes looks up offsets by timestamp for the given partitions. |
|
// |
|
// The returned offset for each partition is the earliest offset whose |
|
// timestamp is greater than or equal to the given timestamp in the |
|
// corresponding partition. If the provided timestamp exceeds that of the |
|
// last message in the partition, a value of -1 will be returned. |
|
// |
|
// The timestamps to query are represented as `.Offset` in the `times` |
|
// argument and the looked up offsets are represented as `.Offset` in the returned |
|
// `offsets` list. |
|
// |
|
// The function will block for at most timeoutMs milliseconds. |
|
// |
|
// Duplicate Topic+Partitions are not supported. |
|
// Per-partition errors may be returned in the `.Error` field. |
|
func offsetsForTimes(H Handle, times []TopicPartition, timeoutMs int) (offsets []TopicPartition, err error) { |
|
cparts := newCPartsFromTopicPartitions(times) |
|
defer C.rd_kafka_topic_partition_list_destroy(cparts) |
|
cerr := C.rd_kafka_offsets_for_times(H.gethandle().rk, cparts, C.int(timeoutMs)) |
|
if cerr != C.RD_KAFKA_RESP_ERR_NO_ERROR { |
|
return nil, newError(cerr) |
|
} |
|
|
|
return newTopicPartitionsFromCparts(cparts), nil |
|
}
|
|
|